summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json2
-rw-r--r--buildpipeline/DotNet-CoreClr-Trusted-Linux.json4
-rw-r--r--dependencies.props6
-rw-r--r--dir.props1
-rw-r--r--src/dlls/mscorrc/mscorrc.rc2
-rw-r--r--src/dlls/mscorrc/resource.h2
-rw-r--r--src/ilasm/assem.cpp1
-rw-r--r--src/ilasm/assembler.cpp18
-rw-r--r--src/ilasm/typar.hpp28
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs10
-rw-r--r--src/vm/classcompat.cpp31
-rw-r--r--src/vm/clsload.cpp34
-rw-r--r--src/vm/jitinterface.cpp18
-rw-r--r--src/vm/jitinterface.h3
-rw-r--r--src/vm/method.cpp20
-rw-r--r--src/vm/method.hpp8
-rw-r--r--src/vm/methodimpl.cpp14
-rw-r--r--src/vm/methodimpl.h5
-rw-r--r--src/vm/methodtable.cpp482
-rw-r--r--src/vm/methodtable.h8
-rw-r--r--src/vm/methodtable.inl5
-rw-r--r--src/vm/methodtablebuilder.cpp400
-rw-r--r--src/vm/methodtablebuilder.h27
-rw-r--r--tests/src/IL.targets3
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs185
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il456
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj37
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs255
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il944
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj37
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs96
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il357
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj37
-rwxr-xr-xtests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs316
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il1677
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj37
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs68
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il275
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj37
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs123
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il397
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj37
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs94
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il252
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj37
-rw-r--r--tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il6
-rw-r--r--tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il5
-rw-r--r--tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il5
-rw-r--r--tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il6
50 files changed, 6577 insertions, 335 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5dfbc40310..9b24a77e90 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -349,6 +349,10 @@ if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /PDBCOMPRESS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864")
+ # Temporarily disable incremental link due to incremental linking CFG bug crashing crossgen.
+ # See https://github.com/dotnet/coreclr/issues/12592
+ set(NO_INCREMENTAL_LINKER_FLAGS "/INCREMENTAL:NO")
+
# Debug build specific flags
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/NOVCFEATURE ${NO_INCREMENTAL_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${NO_INCREMENTAL_LINKER_FLAGS}")
diff --git a/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json b/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json
index f578be4797..a975bbd85b 100644
--- a/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json
+++ b/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json
@@ -345,7 +345,7 @@
"value": "Release"
},
"GitHubRepo": {
- "value": "http://github.com/dotnet/coreclr.git"
+ "value": "https://github.com/dotnet/coreclr.git"
},
"GitHubDirectory": {
"value": "/root/coreclr"
diff --git a/buildpipeline/DotNet-CoreClr-Trusted-Linux.json b/buildpipeline/DotNet-CoreClr-Trusted-Linux.json
index 711b7b0fe2..9c2b4af20f 100644
--- a/buildpipeline/DotNet-CoreClr-Trusted-Linux.json
+++ b/buildpipeline/DotNet-CoreClr-Trusted-Linux.json
@@ -309,7 +309,7 @@
"value": "Release"
},
"GitHubRepo": {
- "value": "http://github.com/dotnet/coreclr.git"
+ "value": "https://github.com/dotnet/coreclr.git"
},
"GitHubDirectory": {
"value": "/root/coreclr"
@@ -449,4 +449,4 @@
"state": "wellFormed",
"revision": 418097633
}
-} \ No newline at end of file
+}
diff --git a/dependencies.props b/dependencies.props
index ad6b4fa126..3d2d605a5f 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -8,7 +8,7 @@
<StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">false</StabilizePackageVersion>
<StableVersion Condition="'$(StabilizePackageVersion)' == 'true' and '$(StableVersion)' == ''">$(PackageVersion)</StableVersion>
- <PreReleaseLabel>preview1</PreReleaseLabel>
+ <PreReleaseLabel>dev-di</PreReleaseLabel>
</PropertyGroup>
<!-- Source of truth for dependency tooling: the commit hash of the dotnet/versions master branch as of the last auto-upgrade. -->
@@ -28,7 +28,7 @@
<!-- Full package version strings that are used in other parts of the build. -->
<PropertyGroup>
- <CoreClrPackageVersion>2.1.0-preview1-25713-01</CoreClrPackageVersion>
+ <CoreClrPackageVersion>2.1.0-dev-di-25528-01</CoreClrPackageVersion>
<XunitPackageVersion>2.2.0-beta2-build3300</XunitPackageVersion>
<XUnitConsoleNetCoreVersion>1.0.2-prerelease-00177</XUnitConsoleNetCoreVersion>
<XUnitPerformanceApiVersion>1.0.0-beta-build0007</XUnitPerformanceApiVersion>
@@ -39,7 +39,7 @@
<!-- Package dependency verification/auto-upgrade configuration. -->
<PropertyGroup>
<BaseDotNetBuildInfo>build-info/dotnet/</BaseDotNetBuildInfo>
- <DependencyBranch>master</DependencyBranch>
+ <DependencyBranch>dev/defaultintf</DependencyBranch>
<CurrentRefXmlPath>$(MSBuildThisFileFullPath)</CurrentRefXmlPath>
</PropertyGroup>
diff --git a/dir.props b/dir.props
index 45545d3849..f8c48d50d7 100644
--- a/dir.props
+++ b/dir.props
@@ -127,6 +127,7 @@
<!-- Packaging properties -->
<PropertyGroup>
<LicenseUrl>https://github.com/dotnet/coreclr/blob/master/LICENSE.TXT</LicenseUrl>
+ <PreReleaseLabel>dev-di</PreReleaseLabel>
<PackageDescriptionFile>$(SourceDir).nuget/descriptions.json</PackageDescriptionFile>
<PackageLicenseFile>$(ProjectDir)LICENSE.TXT</PackageLicenseFile>
<PackageThirdPartyNoticesFile>$(ProjectDir)THIRD-PARTY-NOTICES.TXT</PackageThirdPartyNoticesFile>
diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc
index 8dd29ae75f..7049c42bf8 100644
--- a/src/dlls/mscorrc/mscorrc.rc
+++ b/src/dlls/mscorrc/mscorrc.rc
@@ -1252,6 +1252,8 @@ BEGIN
IDS_CLASSLOAD_MI_VIRTUALMISMATCH "Method '%3' on type '%1' from assembly '%2' tried to implement a method declaration with a different virtual state."
IDS_CLASSLOAD_MI_MUSTBEVIRTUAL "Method '%3' on type '%1' from assembly '%2' must be virtual to implement a method on an interface or super type."
IDS_CLASSLOAD_MI_BAD_SIG "Type '%1' from assembly '%2' contains an invalid method implementation signature."
+ IDS_CLASSLOAD_MI_FINAL_IMPL "Method implementation on an interface '%1' from assembly '%2' must be a final method."
+ IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE "Could not call method '%1' on interface '%2' with type '%3' from assembly '%4' because there are more than one incompatible interface method overriding this method."
IDS_CLASSLOAD_MISSINGMETHODRVA "Could not load type '%1' from assembly '%2' because the method '%3' has no implementation (no RVA)."
SECURITY_E_INCOMPATIBLE_EVIDENCE "Assembly '%1' already loaded without additional security evidence."
diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h
index 205445acbe..39bc8fa9f1 100644
--- a/src/dlls/mscorrc/resource.h
+++ b/src/dlls/mscorrc/resource.h
@@ -613,6 +613,8 @@
#define IDS_EE_SIMD_PARTIAL_TRUST_DISALLOWED 0x1ac4
#define IDS_IBC_MISSING_EXTERNAL_TYPE 0x1ac5
#define IDS_IBC_MISSING_EXTERNAL_METHOD 0x1ac6
+#define IDS_CLASSLOAD_MI_FINAL_IMPL 0x1ac7
+#define IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE 0x1ac8
#define BFA_INVALID_FILE_TOKEN 0x2000
#define BFA_INVALID_TOKEN_TYPE 0x2001
diff --git a/src/ilasm/assem.cpp b/src/ilasm/assem.cpp
index 6416dfe5c7..a3b8daf8ae 100644
--- a/src/ilasm/assem.cpp
+++ b/src/ilasm/assem.cpp
@@ -339,7 +339,6 @@ BOOL Assembler::AddMethod(Method *pMethod)
{
char sz[1024];
sz[0] = 0;
- if(fIsInterface && (!IsMdStatic(pMethod->m_Attr))) strcat_s(sz,1024," non-static declared in interface");
if(fIsImport) strcat_s(sz,1024," imported");
if(IsMdAbstract(pMethod->m_Attr)) strcat_s(sz,1024," abstract");
if(IsMdPinvokeImpl(pMethod->m_Attr)) strcat_s(sz,1024," pinvoke");
diff --git a/src/ilasm/assembler.cpp b/src/ilasm/assembler.cpp
index be535abce8..74190b7e0c 100644
--- a/src/ilasm/assembler.cpp
+++ b/src/ilasm/assembler.cpp
@@ -705,24 +705,6 @@ void Assembler::StartMethod(__in __nullterminated char* name, BinStr* sig, CorMe
{
flags = (CorMethodAttr)(flags | mdSpecialName);
if(IsTdInterface(m_pCurClass->m_Attr)) report->error("Instance constructor in interface\n");
-
- }
- if(!IsMdStatic(flags))
- {
- if(IsTdInterface(m_pCurClass->m_Attr))
- {
- if(!IsMdPublic(flags)) report->error("Non-public instance method in interface\n");
- if((!(IsMdVirtual(flags) && IsMdAbstract(flags))))
- {
- if(OnErrGo) report->error("Non-virtual, non-abstract instance method in interface\n");
- else
- {
- report->warn("Non-virtual, non-abstract instance method in interface, set to such\n");
- flags = (CorMethodAttr)(flags |mdVirtual | mdAbstract);
- }
- }
-
- }
}
m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags);
}
diff --git a/src/ilasm/typar.hpp b/src/ilasm/typar.hpp
index 143a4a2da3..146128e30a 100644
--- a/src/ilasm/typar.hpp
+++ b/src/ilasm/typar.hpp
@@ -51,17 +51,27 @@ private:
class TyParList {
public:
- TyParList(DWORD a, BinStr* b, LPCUTF8 n, TyParList* nx = NULL)
+ TyParList(DWORD a, BinStr* b, LPCUTF8 n, TyParList* nx = NULL)
{
bound = (b == NULL) ? new BinStr() : b;
bound->appendInt32(0); // zero terminator
- attrs = a; name = n; next = nx;
- };
- ~TyParList()
- {
- if(bound) delete bound;
- if (next) delete next;
- };
+ attrs = a; name = n; next = nx;
+ };
+ ~TyParList()
+ {
+ if( bound) delete bound;
+
+ // To avoid excessive stack usage (especially in debug builds), we break the next chain
+ // and delete as we traverse the link list
+ TyParList *pCur = next;
+ while (pCur != NULL)
+ {
+ TyParList *pTmp = pCur->next;
+ pCur->next = NULL;
+ delete pCur;
+ pCur = pTmp;
+ }
+ };
int Count()
{
TyParList* tp = this;
@@ -154,7 +164,7 @@ public:
TyParList* Next() { return next; };
BinStr* Bound() { return bound; };
private:
- BinStr* bound;
+ BinStr* bound;
LPCUTF8 name;
TyParList* next;
DWORD attrs;
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs
index 090acff559..4978b09b72 100644
--- a/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs
@@ -11,17 +11,19 @@ namespace System.Runtime.CompilerServices
/// </summary>
public const string PortablePdb = nameof(PortablePdb);
+ /// Indicates that this version of runtime supports default interface method implementations.
+ /// </summary>
+ public const string DefaultImplementationsOfInterfaces = nameof(DefaultImplementationsOfInterfaces);
+
/// <summary>
/// Checks whether a certain feature is supported by the Runtime.
/// </summary>
public static bool IsSupported(string feature)
{
- // Features should be added as public const string fields in the same class.
- // Example: public const string FeatureName = nameof(FeatureName);
-
switch (feature)
{
- case nameof(PortablePdb):
+ case PortablePdb:
+ case DefaultImplementationsOfInterfaces:
return true;
}
diff --git a/src/vm/classcompat.cpp b/src/vm/classcompat.cpp
index 384e63fefb..fb97a79e85 100644
--- a/src/vm/classcompat.cpp
+++ b/src/vm/classcompat.cpp
@@ -2612,26 +2612,6 @@ VOID MethodTableBuilder::EnumerateClassMethods()
}
}
- // Some interface checks.
- if (IsInterface())
- {
- if (IsMdVirtual(dwMemberAttrs))
- {
- if (!IsMdAbstract(dwMemberAttrs))
- {
- BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
- }
- }
- else
- {
- // Instance field/method
- if (!IsMdStatic(dwMemberAttrs))
- {
- BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
- }
- }
- }
-
// No synchronized methods in ValueTypes
if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
{
@@ -2797,17 +2777,20 @@ VOID MethodTableBuilder::EnumerateClassMethods()
// If the interface is a standard managed interface then allocate space for an FCall method desc.
Classification = mcFCall;
}
- else
+ else if (IsMdAbstract(dwMemberAttrs))
{
// If COM interop is supported then all other interface MDs may be
// accessed via COM interop <TODO> mcComInterop MDs are BIG -
// this is very often a waste of space </TODO>
+ // @DIM_TODO - What if default interface method is called through COM interop?
Classification = mcComInterop;
}
-#else // !FEATURE_COMINTEROP
- // This codepath is used by remoting
- Classification = mcIL;
+ else
#endif // !FEATURE_COMINTEROP
+ {
+ // This codepath is used by remoting and default interface methods
+ Classification = mcIL;
+ }
}
else
{
diff --git a/src/vm/clsload.cpp b/src/vm/clsload.cpp
index bb71f0b6ed..22b030caa0 100644
--- a/src/vm/clsload.cpp
+++ b/src/vm/clsload.cpp
@@ -5912,19 +5912,35 @@ BOOL ClassLoader::CanAccessFamily(
_ASSERTE(pCurrentClass);
_ASSERTE(pTargetClass);
+ BOOL bIsInterface = pTargetClass->IsInterface();
+
//Look to see if Current is a child of the Target.
while (pCurrentClass) {
- MethodTable *pCurInstance = pCurrentClass;
-
- while (pCurInstance) {
- //This is correct. csc is incredibly lax about generics. Essentially if you are a subclass of
- //any type of generic it lets you access it. Since the standard is totally unclear, mirror that
- //behavior here.
- if (pCurInstance->HasSameTypeDefAs(pTargetClass)) {
- return TRUE;
+ if (bIsInterface)
+ {
+ // Calling a protected interface member
+ MethodTable::InterfaceMapIterator it = pCurrentClass->IterateInterfaceMap();
+ while (it.Next())
+ {
+ // We only loosely check if they are of the same generic type
+ if (it.GetInterface()->HasSameTypeDefAs(pTargetClass))
+ return TRUE;
}
+ }
+ else
+ {
+ MethodTable *pCurInstance = pCurrentClass;
+
+ while (pCurInstance) {
+ //This is correct. csc is incredibly lax about generics. Essentially if you are a subclass of
+ //any type of generic it lets you access it. Since the standard is totally unclear, mirror that
+ //behavior here.
+ if (pCurInstance->HasSameTypeDefAs(pTargetClass)) {
+ return TRUE;
+ }
- pCurInstance = pCurInstance->GetParentMethodTable();
+ pCurInstance = pCurInstance->GetParentMethodTable();
+ }
}
///Looking at 8.5.3, it looks like a protected member of a nested class in a parent type is also
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index aa1365ca3d..d960394e12 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -5210,8 +5210,7 @@ void CEEInfo::getCallInfo(
directCall = true;
}
else
- // Force all interface calls to be interpreted as if they are virtual.
- if (pTargetMD->GetMethodTable()->IsInterface())
+ if (pTargetMD->GetMethodTable()->IsInterface() && pTargetMD->IsVirtual())
{
directCall = false;
}
@@ -5614,7 +5613,7 @@ void CEEInfo::getCallInfo(
pResult->classFlags = getClassAttribsInternal(pResolvedToken->hClass);
pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod);
- getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL);
+ getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, /* isCallSite = */ TRUE);
if (flags & CORINFO_CALLINFO_VERIFICATION)
{
@@ -8283,7 +8282,8 @@ void
CEEInfo::getMethodSigInternal(
CORINFO_METHOD_HANDLE ftnHnd,
CORINFO_SIG_INFO * sigRet,
- CORINFO_CLASS_HANDLE owner)
+ CORINFO_CLASS_HANDLE owner,
+ BOOL isCallSite)
{
STANDARD_VM_CONTRACT;
@@ -8309,7 +8309,15 @@ CEEInfo::getMethodSigInternal(
// Shared generic methods and shared methods on generic structs take an extra argument representing their instantiation
if (ftn->RequiresInstArg())
{
- sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE);
+ //
+ // If we are making an interface call that is a default interface method, we need to lie to the JIT.
+ // The reason being that we already made sure target is always directly callable (through instantiation stubs),
+ // JIT should not generate shared generics aware call code and insert the secret argument again at the callsite.
+ // Otherwise we would end up with two secret generic dictionary arguments (since the stub also provides one).
+ //
+ BOOL isDefaultInterfaceMethodCallSite = isCallSite && ftn->IsDefaultInterfaceMethod();
+ if (!isDefaultInterfaceMethodCallSite)
+ sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE);
}
// We want the calling convention bit to be consistant with the method attribute bit
diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h
index 8ba65c3964..93470ecbac 100644
--- a/src/vm/jitinterface.h
+++ b/src/vm/jitinterface.h
@@ -714,7 +714,8 @@ public:
void getMethodSigInternal (
CORINFO_METHOD_HANDLE ftnHnd,
CORINFO_SIG_INFO* sigInfo,
- CORINFO_CLASS_HANDLE owner = NULL
+ CORINFO_CLASS_HANDLE owner = NULL,
+ BOOL isCallSite = FALSE
);
void getEHinfo(
diff --git a/src/vm/method.cpp b/src/vm/method.cpp
index 4bae82a61d..8778744537 100644
--- a/src/vm/method.cpp
+++ b/src/vm/method.cpp
@@ -1636,7 +1636,11 @@ BOOL MethodDesc::IsSharedByGenericMethodInstantiations()
// Does this method require an extra MethodTable argument for instantiation information?
// This is the case for
// * per-inst static methods in shared-code instantiated generic classes (e.g. static void MyClass<string>::m())
+// - there is no this pointer providing generic dictionary info
// * shared-code instance methods in instantiated generic structs (e.g. void MyValueType<string>::m())
+// - unboxed 'this' pointer in value-type instance methods don't have MethodTable pointer by definition
+// * default interface method called via interface dispatch (e. g. IFoo<string>.Foo calling into IFoo<object>::Foo())
+// - this pointer is ambiguous as it can implement more than one IFoo<T>
BOOL MethodDesc::RequiresInstMethodTableArg()
{
LIMITED_METHOD_DAC_CONTRACT;
@@ -1644,7 +1648,7 @@ BOOL MethodDesc::RequiresInstMethodTableArg()
return
IsSharedByGenericInstantiations() &&
!HasMethodInstantiation() &&
- (IsStatic() || GetMethodTable()->IsValueType());
+ (IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod());
}
//*******************************************************************************
@@ -1666,7 +1670,7 @@ BOOL MethodDesc::RequiresInstArg()
LIMITED_METHOD_DAC_CONTRACT;
BOOL fRet = IsSharedByGenericInstantiations() &&
- (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType());
+ (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod());
_ASSERT(fRet == (RequiresInstMethodTableArg() || RequiresInstMethodDescArg()));
return fRet;
@@ -1742,7 +1746,8 @@ BOOL MethodDesc::AcquiresInstMethodTableFromThis() {
IsSharedByGenericInstantiations() &&
!HasMethodInstantiation() &&
!IsStatic() &&
- !GetMethodTable()->IsValueType();
+ !GetMethodTable()->IsValueType() &&
+ !IsDefaultInterfaceMethod();
}
//*******************************************************************************
@@ -2430,7 +2435,7 @@ BOOL MethodDesc::RequiresStableEntryPoint(BOOL fEstimateForChunk /*=FALSE*/)
return TRUE;
// TODO: Can we avoid early allocation of precodes for interfaces and cominterop?
- if ((IsInterface() && !IsStatic()) || IsComPlusCall())
+ if ((IsInterface() && !IsStatic() && IsVirtual()) || IsComPlusCall())
return TRUE;
}
@@ -2526,7 +2531,7 @@ BOOL MethodDesc::MayHaveNativeCode()
_ASSERTE(IsIL());
- if ((IsInterface() && !IsStatic()) || IsWrapperStub() || ContainsGenericVariables() || IsAbstract())
+ if ((IsInterface() && !IsStatic() && IsVirtual() && IsAbstract()) || IsWrapperStub() || ContainsGenericVariables() || IsAbstract())
{
return FALSE;
}
@@ -4823,6 +4828,11 @@ BOOL MethodDesc::SetNativeCodeInterlocked(PCODE addr, PCODE pExpected /*=NULL*/)
return FastInterlockCompareExchangePointer(EnsureWritablePages(reinterpret_cast<TADDR*>(pSlot)),
(TADDR&)value, (TADDR&)expected) == (TADDR&)expected;
}
+
+ if (IsDefaultInterfaceMethod() && HasPrecode())
+ {
+ return GetPrecode()->SetTargetInterlocked(addr);
+ }
_ASSERTE(pExpected == NULL);
return SetStableEntryPointInterlocked(addr);
diff --git a/src/vm/method.hpp b/src/vm/method.hpp
index 9a20af2212..08318ec5b5 100644
--- a/src/vm/method.hpp
+++ b/src/vm/method.hpp
@@ -1005,6 +1005,14 @@ public:
&& GetSlot() < pMT->GetNumVirtuals();
}
+ // Is this a default interface method (virtual non-abstract instance method)
+ inline BOOL IsDefaultInterfaceMethod()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ return (GetMethodTable()->IsInterface() && !IsStatic() && IsVirtual() && !IsAbstract());
+ }
+
inline BOOL HasNonVtableSlot();
void SetHasNonVtableSlot()
diff --git a/src/vm/methodimpl.cpp b/src/vm/methodimpl.cpp
index c685e1c8a5..b3f8451e22 100644
--- a/src/vm/methodimpl.cpp
+++ b/src/vm/methodimpl.cpp
@@ -72,6 +72,20 @@ PTR_MethodDesc MethodImpl::FindMethodDesc(DWORD slot, PTR_MethodDesc defaultRetu
return defaultReturn;
}
+ return GetMethodDesc(slotIndex, defaultReturn);
+}
+
+PTR_MethodDesc MethodImpl::GetMethodDesc(DWORD slotIndex, PTR_MethodDesc defaultReturn)
+{
+ CONTRACTL
+ {
+ if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
+ if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
+ if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
+ MODE_ANY;
+ }
+ CONTRACTL_END
+
DPTR(RelativePointer<PTR_MethodDesc>) pRelPtrForSlot = GetImpMDsNonNull();
// The method descs are not offset by one
TADDR base = dac_cast<TADDR>(pRelPtrForSlot) + slotIndex * sizeof(RelativePointer<MethodDesc *>);
diff --git a/src/vm/methodimpl.h b/src/vm/methodimpl.h
index 453f4ccd4d..ce915eaf9d 100644
--- a/src/vm/methodimpl.h
+++ b/src/vm/methodimpl.h
@@ -47,7 +47,7 @@ public:
inline WORD GetSlot()
{ WRAPPER_NO_CONTRACT; CONSISTENCY_CHECK(IsValid()); _ASSERTE(FitsIn<WORD>(m_pImpl->GetSlots()[m_iCur])); return static_cast<WORD>(m_pImpl->GetSlots()[m_iCur]); }
inline MethodDesc *GetMethodDesc()
- { WRAPPER_NO_CONTRACT; return m_pImpl->FindMethodDesc(GetSlot(), (PTR_MethodDesc) m_pMD); }
+ { WRAPPER_NO_CONTRACT; return m_pImpl->GetMethodDesc(m_iCur, (PTR_MethodDesc) m_pMD); }
};
#endif // !DACCESS_COMPILE
@@ -129,6 +129,9 @@ public:
// Returns the method desc for the replaced slot;
PTR_MethodDesc FindMethodDesc(DWORD slot, PTR_MethodDesc defaultReturn);
+ // Returns the method desc for the slot index;
+ PTR_MethodDesc GetMethodDesc(DWORD slotIndex, PTR_MethodDesc defaultReturn);
+
private:
static const DWORD INVALID_INDEX = (DWORD)(-1);
DWORD FindSlotIndex(DWORD slot);
diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp
index 32d55d303e..0adba6ac4e 100644
--- a/src/vm/methodtable.cpp
+++ b/src/vm/methodtable.cpp
@@ -1986,7 +1986,7 @@ MethodTable::Debug_DumpInterfaceMap(
HRESULT hr;
EX_TRY
{
- InterfaceMapIterator it(this, false);
+ InterfaceMapIterator it(this);
while (it.Next())
{
MethodTable *pInterfaceMT = it.GetInterface();
@@ -6922,6 +6922,12 @@ MethodTable::FindDispatchImpl(
DispatchMapEntry e;
if (!FindDispatchEntry(typeID, slotNumber, &e))
{
+ // Figure out the interface being called
+ MethodTable *pIfcMT = GetThread()->GetDomain()->LookupType(typeID);
+
+ // Figure out which method of the interface the caller requested.
+ MethodDesc * pIfcMD = pIfcMT->GetMethodDescForSlot(slotNumber);
+
// A call to an array thru IList<T> (or IEnumerable<T> or ICollection<T>) has to be handled specially.
// These interfaces are "magic" (mostly due to working set concerned - they are created on demand internally
// even though semantically, these are static interfaces.)
@@ -6935,7 +6941,7 @@ MethodTable::FindDispatchImpl(
// IList<T> call thru an array.
// Get the MT of IList<T> or IReadOnlyList<T>
- MethodTable *pIfcMT = GetThread()->GetDomain()->LookupType(typeID);
+
// Quick sanity check
if (!(pIfcMT->HasInstantiation()))
@@ -6947,9 +6953,6 @@ MethodTable::FindDispatchImpl(
// Get the type of T (as in IList<T>)
TypeHandle theT = pIfcMT->GetInstantiation()[0];
- // Figure out which method of IList<T> the caller requested.
- MethodDesc * pIfcMD = pIfcMT->GetMethodDescForSlot(slotNumber);
-
// Retrieve the corresponding method of SZArrayHelper. This is the guy that will actually execute.
// This method will be an instantiation of a generic method. I.e. if the caller requested
// IList<T>.Meth(), he will actually be diverted to SZArrayHelper.Meth<T>().
@@ -6966,11 +6969,34 @@ MethodTable::FindDispatchImpl(
RETURN(TRUE);
}
+ else
+ {
+ //
+ // See if we can find a default method from one of the implemented interfaces
+ //
+ MethodDesc *pDefaultMethod = NULL;
+ if (FindDefaultInterfaceImplementation(
+ pIfcMD, // the interface method being resolved
+ pIfcMT, // the interface being resolved
+ &pDefaultMethod))
+ {
+ // Now, construct a DispatchSlot to return in *pImplSlot
+ DispatchSlot ds(pDefaultMethod->GetMethodEntryPoint());
+
+ if (pImplSlot != NULL)
+ {
+ *pImplSlot = ds;
+ }
+
+ RETURN(TRUE);
+ }
+ }
// This contract is not implemented by this class or any parent class.
RETURN(FALSE);
}
+
/////////////////////////////////
// 1.1. Update the typeID and slotNumber so that the full search can commense below
typeID = TYPE_ID_THIS_CLASS;
@@ -6988,6 +7014,273 @@ MethodTable::FindDispatchImpl(
RETURN (TRUE);
}
+#ifndef DACCESS_COMPILE
+
+struct MatchCandidate
+{
+ MethodTable *pMT;
+ MethodDesc *pMD;
+};
+
+void ThrowExceptionForConflictingOverride(
+ MethodTable *pTargetClass,
+ MethodTable *pInterfaceMT,
+ MethodDesc *pInterfaceMD)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ SString assemblyName;
+
+ pTargetClass->GetAssembly()->GetDisplayName(assemblyName);
+
+ SString strInterfaceName;
+ TypeString::AppendType(strInterfaceName, TypeHandle(pInterfaceMT));
+
+ SString strMethodName;
+ TypeString::AppendMethod(strMethodName, pInterfaceMD, pInterfaceMD->GetMethodInstantiation());
+
+ SString strTargetClassName;
+ TypeString::AppendType(strTargetClassName, pTargetClass);
+
+ COMPlusThrow(
+ kNotSupportedException,
+ IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE,
+ strInterfaceName,
+ strMethodName,
+ strTargetClassName,
+ assemblyName);
+}
+
+// Find the default interface implementation method for interface dispatch
+// It is either the interface method with default interface method implementation,
+// or an most specific interface with an explicit methodimpl overriding the method
+BOOL MethodTable::FindDefaultInterfaceImplementation(
+ MethodDesc *pInterfaceMD,
+ MethodTable *pInterfaceMT,
+ MethodDesc **ppDefaultMethod
+)
+{
+ CONTRACT(BOOL) {
+ INSTANCE_CHECK;
+ MODE_ANY;
+ THROWS;
+ GC_TRIGGERS;
+ PRECONDITION(CheckPointer(pInterfaceMD));
+ PRECONDITION(CheckPointer(pInterfaceMT));
+ PRECONDITION(CheckPointer(ppDefaultMethod));
+ POSTCONDITION(!RETVAL || (*ppDefaultMethod) != nullptr);
+ } CONTRACT_END;
+
+ InterfaceMapIterator it = this->IterateInterfaceMap();
+
+ CQuickArray<MatchCandidate> candidates;
+ int candidatesCount = 0;
+ candidates.AllocThrows(this->GetNumInterfaces());
+
+ //
+ // Walk interface from derived class to parent class
+ // We went with a straight-forward implementation as in most cases the number of interfaces are small
+ // and the result of the interface dispatch are already cached. If there are significant usage of default
+ // interface methods in highly complex interface hierarchies we can revisit this
+ //
+ MethodTable *pMT = this;
+ while (pMT != NULL)
+ {
+ MethodTable *pParentMT = pMT->GetParentMethodTable();
+ unsigned dwParentInterfaces = 0;
+ if (pParentMT)
+ dwParentInterfaces = pParentMT->GetNumInterfaces();
+
+ // Scanning only current class only if the current class have more interface than parent
+ // (parent interface are laid out first in interface map)
+ if (pMT->GetNumInterfaces() > dwParentInterfaces)
+ {
+ // Only iterate the interfaceimpls on current class
+ MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMapFrom(dwParentInterfaces);
+ while (!it.Finished())
+ {
+ MethodTable *pCurMT = it.GetInterface();
+
+ MethodDesc *pCurMD = NULL;
+ if (pCurMT == pInterfaceMT)
+ {
+ if (!pInterfaceMD->IsAbstract())
+ {
+ // exact match
+ pCurMD = pInterfaceMD;
+ }
+ }
+ else if (pCurMT->CanCastToInterface(pInterfaceMT))
+ {
+ if (pCurMT->HasSameTypeDefAs(pInterfaceMT))
+ {
+ // Generic variance match - we'll instantiate pCurMD with the right type arguments later
+ pCurMD = pInterfaceMD;
+ }
+ else
+ {
+ //
+ // A more specific interface - search for an methodimpl for explicit override
+ // Implicit override in default interface methods are not allowed
+ //
+ MethodIterator methodIt(pCurMT);
+ for (; methodIt.IsValid(); methodIt.Next())
+ {
+ MethodDesc *pMD = methodIt.GetMethodDesc();
+ int targetSlot = pInterfaceMD->GetSlot();
+
+ if (pMD->IsMethodImpl())
+ {
+ MethodImpl::Iterator it(pMD);
+ for (; it.IsValid(); it.Next())
+ {
+ MethodDesc *pDeclMD = it.GetMethodDesc();
+
+ if (pDeclMD->GetSlot() != targetSlot)
+ continue;
+
+ MethodTable *pDeclMT = pDeclMD->GetMethodTable();
+ if (pDeclMT->ContainsGenericVariables())
+ {
+ TypeHandle thInstDeclMT = ClassLoader::LoadGenericInstantiationThrowing(
+ pDeclMT->GetModule(),
+ pDeclMT->GetCl(),
+ pCurMT->GetInstantiation());
+ MethodTable *pInstDeclMT = thInstDeclMT.GetMethodTable();
+ if (pInstDeclMT == pInterfaceMT)
+ {
+ // This is a matching override. We'll instantiate pCurMD later
+ pCurMD = pMD;
+ break;
+ }
+ }
+ else if (pDeclMD == pInterfaceMD)
+ {
+ // Exact match override
+ pCurMD = pMD;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (pCurMD != NULL)
+ {
+ //
+ // Found a match. But is it a more specific match (we want most specific interfaces)
+ //
+ if (pCurMD->HasClassOrMethodInstantiation())
+ {
+ // Instantiate the MethodDesc
+ // We don't want generic dictionary from this pointer - we need pass secret type argument
+ // from instantiating stubs to resolve ambiguity
+ pCurMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
+ pCurMD,
+ pCurMT,
+ FALSE, // forceBoxedEntryPoint
+ pCurMD->HasMethodInstantiation() ?
+ pCurMD->AsInstantiatedMethodDesc()->IMD_GetMethodInstantiation() :
+ Instantiation(), // for method themselves that are generic
+ FALSE, // allowInstParam
+ TRUE // forceRemoteableMethod
+ );
+ }
+
+ bool needToInsert = true;
+ bool seenMoreSpecific = false;
+
+ // We need to maintain the invariant that the candidates are always the most specific
+ // in all path scaned so far. There might be multiple incompatible candidates
+ for (int i = 0; i < candidatesCount; ++i)
+ {
+ MethodTable *pCandidateMT = candidates[i].pMT;
+ if (pCandidateMT == NULL)
+ continue;
+
+ if (pCandidateMT == pCurMT)
+ {
+ // A dup - we are done
+ needToInsert = false;
+ break;
+ }
+
+ if (pCurMT->CanCastToInterface(pCandidateMT))
+ {
+ // pCurMT is a more specific choice than IFoo/IBar both overrides IBlah :
+ if (!seenMoreSpecific)
+ {
+ seenMoreSpecific = true;
+ candidates[i].pMT = pCurMT;
+ candidates[i].pMD = pCurMD;
+ }
+ else
+ {
+ candidates[i].pMT = NULL;
+ candidates[i].pMD = NULL;
+ }
+
+ needToInsert = false;
+ }
+ else if (pCandidateMT->CanCastToInterface(pCurMT))
+ {
+ // pCurMT is less specific - we don't need to scan more entries as this entry can
+ // represent pCurMT (other entries are incompatible with pCurMT)
+ needToInsert = false;
+ break;
+ }
+ else
+ {
+ // pCurMT is incompatible - keep scanning
+ }
+ }
+
+ if (needToInsert)
+ {
+ ASSERT(candidatesCount < candidates.Size());
+ candidates[candidatesCount].pMT = pCurMT;
+ candidates[candidatesCount].pMD = pCurMD;
+ candidatesCount++;
+ }
+ }
+
+ it.Next();
+ }
+ }
+
+ pMT = pParentMT;
+ }
+
+ // scan to see if there are any conflicts
+ MethodTable *pBestCandidateMT = NULL;
+ MethodDesc *pBestCandidateMD = NULL;
+ for (int i = 0; i < candidatesCount; ++i)
+ {
+ if (candidates[i].pMT == NULL)
+ continue;
+
+ if (pBestCandidateMT == NULL)
+ {
+ pBestCandidateMT = candidates[i].pMT;
+ pBestCandidateMD = candidates[i].pMD;
+ }
+ else if (pBestCandidateMT != candidates[i].pMT)
+ {
+ ThrowExceptionForConflictingOverride(this, pInterfaceMT, pInterfaceMD);
+ }
+ }
+
+ if (pBestCandidateMD != NULL)
+ {
+ *ppDefaultMethod = pBestCandidateMD;
+ RETURN(TRUE);
+ }
+
+ RETURN(FALSE);
+}
+#endif // DACCESS_COMPILE
+
//==========================================================================================
DispatchSlot MethodTable::FindDispatchSlot(UINT32 typeID, UINT32 slotNumber)
{
@@ -9538,79 +9831,79 @@ MethodTable::TryResolveConstraintMethodApprox(
// we don't have enough exact type information at JIT time
// even to decide whether we will be able to resolve to an unboxed entry point...
// To cope with this case we always go via the helper function if there's any
- // chance of this happening by checking for all interfaces which might possibly
- // be compatible with the call (verification will have ensured that
- // at least one of them will be)
-
- // Enumerate all potential interface instantiations
- MethodTable::InterfaceMapIterator it = pCanonMT->IterateInterfaceMap();
- DWORD cPotentialMatchingInterfaces = 0;
- while (it.Next())
+// chance of this happening by checking for all interfaces which might possibly
+// be compatible with the call (verification will have ensured that
+// at least one of them will be)
+
+// Enumerate all potential interface instantiations
+MethodTable::InterfaceMapIterator it = pCanonMT->IterateInterfaceMap();
+DWORD cPotentialMatchingInterfaces = 0;
+while (it.Next())
+{
+ TypeHandle thPotentialInterfaceType(it.GetInterface());
+ if (thPotentialInterfaceType.AsMethodTable()->GetCanonicalMethodTable() ==
+ thInterfaceType.AsMethodTable()->GetCanonicalMethodTable())
+ {
+ cPotentialMatchingInterfaces++;
+ pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD);
+
+ // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
+ if ((pMD != NULL) && !pMD->GetMethodTable()->IsValueType())
{
- TypeHandle thPotentialInterfaceType(it.GetInterface());
- if (thPotentialInterfaceType.AsMethodTable()->GetCanonicalMethodTable() ==
- thInterfaceType.AsMethodTable()->GetCanonicalMethodTable())
- {
- cPotentialMatchingInterfaces++;
- pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD);
-
- // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
- if ((pMD != NULL) && !pMD->GetMethodTable()->IsValueType())
- {
- LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: %s::%s not a value type method\n",
- pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
- return NULL;
- }
- }
+ LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: %s::%s not a value type method\n",
+ pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
+ return NULL;
}
-
- _ASSERTE_MSG((cPotentialMatchingInterfaces != 0),
- "At least one interface has to implement the method, otherwise there's a bug in JIT/verification.");
+ }
+}
- if (cPotentialMatchingInterfaces > 1)
- { // We have more potentially matching interfaces
- MethodTable * pInterfaceMT = thInterfaceType.GetMethodTable();
- _ASSERTE(pInterfaceMT->HasInstantiation());
-
- BOOL fIsExactMethodResolved = FALSE;
-
- if (!pInterfaceMT->IsSharedByGenericInstantiations() &&
- !pInterfaceMT->IsGenericTypeDefinition() &&
- !this->IsSharedByGenericInstantiations() &&
- !this->IsGenericTypeDefinition())
- { // We have exact interface and type instantiations (no generic variables and __Canon used
- // anywhere)
- if (this->CanCastToInterface(pInterfaceMT))
- {
- // We can resolve to exact method
- pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD);
- _ASSERTE(pMD != NULL);
- fIsExactMethodResolved = TRUE;
- }
- }
-
- if (!fIsExactMethodResolved)
- { // We couldn't resolve the interface statically
- _ASSERTE(pfForceUseRuntimeLookup != NULL);
- // Notify the caller that it should use runtime lookup
- // Note that we can leave pMD incorrect, because we will use runtime lookup
- *pfForceUseRuntimeLookup = TRUE;
- }
+_ASSERTE_MSG((cPotentialMatchingInterfaces != 0),
+ "At least one interface has to implement the method, otherwise there's a bug in JIT/verification.");
+
+if (cPotentialMatchingInterfaces > 1)
+{ // We have more potentially matching interfaces
+ MethodTable * pInterfaceMT = thInterfaceType.GetMethodTable();
+ _ASSERTE(pInterfaceMT->HasInstantiation());
+
+ BOOL fIsExactMethodResolved = FALSE;
+
+ if (!pInterfaceMT->IsSharedByGenericInstantiations() &&
+ !pInterfaceMT->IsGenericTypeDefinition() &&
+ !this->IsSharedByGenericInstantiations() &&
+ !this->IsGenericTypeDefinition())
+ { // We have exact interface and type instantiations (no generic variables and __Canon used
+ // anywhere)
+ if (this->CanCastToInterface(pInterfaceMT))
+ {
+ // We can resolve to exact method
+ pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD);
+ _ASSERTE(pMD != NULL);
+ fIsExactMethodResolved = TRUE;
}
- else
+ }
+
+ if (!fIsExactMethodResolved)
+ { // We couldn't resolve the interface statically
+ _ASSERTE(pfForceUseRuntimeLookup != NULL);
+ // Notify the caller that it should use runtime lookup
+ // Note that we can leave pMD incorrect, because we will use runtime lookup
+ *pfForceUseRuntimeLookup = TRUE;
+ }
+}
+else
+{
+ // If we can resolve the interface exactly then do so (e.g. when doing the exact
+ // lookup at runtime, or when not sharing generic code).
+ if (pCanonMT->CanCastToInterface(thInterfaceType.GetMethodTable()))
+ {
+ pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD);
+ if (pMD == NULL)
{
- // If we can resolve the interface exactly then do so (e.g. when doing the exact
- // lookup at runtime, or when not sharing generic code).
- if (pCanonMT->CanCastToInterface(thInterfaceType.GetMethodTable()))
- {
- pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD);
- if (pMD == NULL)
- {
- LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: failed to find method desc for interface method\n"));
- }
- }
+ LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: failed to find method desc for interface method\n"));
}
}
+}
+ }
else if (pGenInterfaceMD->IsVirtual())
{
if (pGenInterfaceMD->HasNonVtableSlot() && pGenInterfaceMD->GetMethodTable()->IsValueType())
@@ -9631,33 +9924,36 @@ MethodTable::TryResolveConstraintMethodApprox(
// methods on System.Object, i.e. when these are used as a constraint.
pMD = NULL;
}
-
+
if (pMD == NULL)
{ // Fall back to VSD
return NULL;
}
-
- //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
- // Only return a method if the value type itself declares the method,
- // otherwise we might get a method from Object or System.ValueType
- if (!pMD->GetMethodTable()->IsValueType())
- { // Fall back to VSD
- return NULL;
+
+ if (!pMD->GetMethodTable()->IsInterface())
+ {
+ //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
+ // Only return a method if the value type itself declares the method
+ // otherwise we might get a method from Object or System.ValueType
+ if (!pMD->GetMethodTable()->IsValueType())
+ { // Fall back to VSD
+ return NULL;
+ }
+
+ // We've resolved the method, ignoring its generic method arguments
+ // If the method is a generic method then go and get the instantiated descriptor
+ pMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
+ pMD,
+ this,
+ FALSE /* no BoxedEntryPointStub */,
+ pInterfaceMD->GetMethodInstantiation(),
+ FALSE /* no allowInstParam */);
+
+ // FindOrCreateAssociatedMethodDesc won't return an BoxedEntryPointStub.
+ _ASSERTE(pMD != NULL);
+ _ASSERTE(!pMD->IsUnboxingStub());
}
-
- // We've resolved the method, ignoring its generic method arguments
- // If the method is a generic method then go and get the instantiated descriptor
- pMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
- pMD,
- this,
- FALSE /* no BoxedEntryPointStub */ ,
- pInterfaceMD->GetMethodInstantiation(),
- FALSE /* no allowInstParam */ );
-
- // FindOrCreateAssociatedMethodDesc won't return an BoxedEntryPointStub.
- _ASSERTE(pMD != NULL);
- _ASSERTE(!pMD->IsUnboxingStub());
-
+
return pMD;
} // MethodTable::TryResolveConstraintMethodApprox
diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h
index e5fd7fad07..60059675e9 100644
--- a/src/vm/methodtable.h
+++ b/src/vm/methodtable.h
@@ -2548,6 +2548,14 @@ public:
UINT32 slotNumber,
DispatchSlot * pImplSlot);
+
+#ifndef DACCESS_COMPILE
+ BOOL FindDefaultInterfaceImplementation(
+ MethodDesc *pInterfaceMD,
+ MethodTable *pObjectMT,
+ MethodDesc **ppDefaultMethod);
+#endif // DACCESS_COMPILE
+
DispatchSlot FindDispatchSlot(UINT32 typeID, UINT32 slotNumber);
DispatchSlot FindDispatchSlot(DispatchToken tok);
diff --git a/src/vm/methodtable.inl b/src/vm/methodtable.inl
index 0d0acda885..4fa81c931b 100644
--- a/src/vm/methodtable.inl
+++ b/src/vm/methodtable.inl
@@ -652,9 +652,8 @@ inline MethodDesc* MethodTable::GetMethodDescForSlot(DWORD slot)
PCODE pCode = GetRestoredSlot(slot);
- // This is an optimization that we can take advantage of if we're trying
- // to get the MethodDesc for an interface virtual, since their slots
- // always point to the stub.
+ // This is an optimization that we can take advantage of if we're trying to get the MethodDesc
+ // for an interface virtual, since their slots usually point to stub.
if (IsInterface() && slot < GetNumVirtuals())
{
return MethodDesc::GetMethodDescFromStubAddr(pCode);
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index cdee2d8667..f9876608eb 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -1619,19 +1619,28 @@ MethodTableBuilder::BuildMethodTableThrowing(
// Allocate MethodDescs (expects methods placed methods)
AllocAndInitMethodDescs();
- //
- // If we are a class, then there may be some unplaced vtable methods (which are by definition
- // interface methods, otherwise they'd already have been placed). Place as many unplaced methods
- // as possible, in the order preferred by interfaces. However, do not allow any duplicates - once
- // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
- // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot. Fill out the interface
- // map for all interfaces as they are placed.
- //
- // If we are an interface, then all methods are already placed. Fill out the interface map for
- // interfaces as they are placed.
- //
- if (!IsInterface())
+ if (IsInterface())
+ {
+ //
+ // We need to process/place method impls for default interface method overrides.
+ // We won't build dispatch map for interfaces, though.
+ //
+ ProcessMethodImpls();
+ PlaceMethodImpls();
+ }
+ else
{
+ //
+ // If we are a class, then there may be some unplaced vtable methods (which are by definition
+ // interface methods, otherwise they'd already have been placed). Place as many unplaced methods
+ // as possible, in the order preferred by interfaces. However, do not allow any duplicates - once
+ // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
+ // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot. Fill out the interface
+ // map for all interfaces as they are placed.
+ //
+ // If we are an interface, then all methods are already placed. Fill out the interface map for
+ // interfaces as they are placed.
+ //
ComputeInterfaceMapEquivalenceSet();
PlaceInterfaceMethods();
@@ -2842,16 +2851,16 @@ MethodTableBuilder::EnumerateClassMethods()
BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD);
}
}
- else if(fIsClassInterface)
- {
- if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs))
- {
- CONSISTENCY_CHECK(CheckPointer(strMethodName));
- if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME))
- {
- BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT);
- }
- }
+ else if(fIsClassInterface)
+ {
+ if (IsMdRTSpecialName(dwMemberAttrs))
+ {
+ CONSISTENCY_CHECK(CheckPointer(strMethodName));
+ if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME))
+ {
+ BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT);
+ }
+ }
}
// Virtual / not virtual
@@ -2871,26 +2880,6 @@ MethodTableBuilder::EnumerateClassMethods()
}
}
- // Some interface checks.
- if (IsInterface())
- {
- if (IsMdVirtual(dwMemberAttrs))
- {
- if (!IsMdAbstract(dwMemberAttrs))
- {
- BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
- }
- }
- else
- {
- // Instance field/method
- if (!IsMdStatic(dwMemberAttrs))
- {
- BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
- }
- }
- }
-
// No synchronized methods in ValueTypes
if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
{
@@ -3113,7 +3102,7 @@ MethodTableBuilder::EnumerateClassMethods()
type = METHOD_TYPE_NORMAL;
}
else if (bmtGenerics->GetNumGenericArgs() != 0 &&
- (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT())))
+ (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT())))
{
// Methods in instantiated interfaces need nothing special - they are not visible from COM etc.
// mcComInterop is only useful for unshared instantiated WinRT interfaces. If the interface is
@@ -3125,7 +3114,7 @@ MethodTableBuilder::EnumerateClassMethods()
// If the interface is a standard managed interface then allocate space for an FCall method desc.
type = METHOD_TYPE_FCALL;
}
- else
+ else if (IsMdAbstract(dwMemberAttrs))
{
// If COM interop is supported then all other interface MDs may be
// accessed via COM interop. mcComInterop MDs have an additional
@@ -3133,10 +3122,12 @@ MethodTableBuilder::EnumerateClassMethods()
// allocated lazily when/if the MD actually gets used for interop.
type = METHOD_TYPE_COMINTEROP;
}
-#else // !FEATURE_COMINTEROP
- // This codepath is used by remoting
- type = METHOD_TYPE_NORMAL;
+ else
#endif // !FEATURE_COMINTEROP
+ {
+ // This codepath is used by remoting
+ type = METHOD_TYPE_NORMAL;
+ }
}
else
{
@@ -4752,6 +4743,12 @@ VOID MethodTableBuilder::TestMethodImpl(
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
}
+ // Interface method body that has methodimpl should always be final
+ if (IsInterface() && !IsMdFinal(dwImplAttrs))
+ {
+ BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
+ }
+
// Since MethodImpl's do not affect the visibility of the Decl method, there's
// no need to check.
@@ -5548,6 +5545,9 @@ MethodTableBuilder::ProcessMethodImpls()
{
STANDARD_VM_CONTRACT;
+ if (bmtMethod->dwNumberMethodImpls == 0)
+ return;
+
HRESULT hr = S_OK;
DeclaredMethodIterator it(*this);
@@ -5679,49 +5679,60 @@ MethodTableBuilder::ProcessMethodImpls()
}
}
- if (pDeclType == NULL)
+ if (IsInterface())
{
- DWORD equivalenceSet = 0;
-
- for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
- {
- bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
- // Type Equivalence is respected for this comparision as we just need to find an
- // equivalent interface, the particular interface is unimportant
- if (MetaSig::CompareTypeDefsUnderSubstitutions(
- pCurItf->GetMethodTable(), pDeclMT,
- &pCurItf->GetSubstitution(), pDeclSubst,
- NULL))
- {
- equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
- pItfEntry = &bmtInterface->pInterfaceMap[i];
- break;
- }
- }
-
- if (equivalenceSet == 0)
+ if (pDeclType == NULL)
{
// Interface is not implemented by this type.
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
}
-
- // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
- // as the only match may be one of the non-exact matches
- bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
- bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
- bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
- bmtMethod->dwNumberInexactMethodImplCandidates++;
- continue; // Move on to other MethodImpls
}
else
{
- // This method impl may need to match other methods during inexact processing
- if (pItfEntry->InEquivalenceSetWithMultipleEntries())
+ if (pDeclType == NULL)
{
+ DWORD equivalenceSet = 0;
+
+ for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
+ {
+ bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
+ // Type Equivalence is respected for this comparision as we just need to find an
+ // equivalent interface, the particular interface is unimportant
+ if (MetaSig::CompareTypeDefsUnderSubstitutions(
+ pCurItf->GetMethodTable(), pDeclMT,
+ &pCurItf->GetSubstitution(), pDeclSubst,
+ NULL))
+ {
+ equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
+ pItfEntry = &bmtInterface->pInterfaceMap[i];
+ break;
+ }
+ }
+
+ if (equivalenceSet == 0)
+ {
+ // Interface is not implemented by this type.
+ BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
+ }
+
+ // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
+ // as the only match may be one of the non-exact matches
bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
- bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
- bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
+ bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
+ bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
bmtMethod->dwNumberInexactMethodImplCandidates++;
+ continue; // Move on to other MethodImpls
+ }
+ else
+ {
+ // This method impl may need to match other methods during inexact processing
+ if (pItfEntry->InEquivalenceSetWithMultipleEntries())
+ {
+ bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
+ bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
+ bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
+ bmtMethod->dwNumberInexactMethodImplCandidates++;
+ }
}
}
@@ -5823,7 +5834,7 @@ MethodTableBuilder::ProcessMethodImpls()
{ // Method not found, throw.
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
}
-
+
if (!IsMdVirtual(declMethod.GetDeclAttrs()))
{ // Make sure the decl is virtual
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
@@ -6128,9 +6139,12 @@ MethodTableBuilder::PlaceMethodImpls()
}
// Allocate some temporary storage. The number of overrides for a single method impl
- // cannot be greater then the number of vtable slots.
- DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[bmtVT->cVirtualSlots];
- RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[bmtVT->cVirtualSlots];
+ // cannot be greater then the number of vtable slots for classes. But for interfaces
+ // it might contain overrides for other interface methods.
+ DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
+
+ DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[dwMaxSlotSize];
+ RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[dwMaxSlotSize];
DWORD iEntry = 0;
bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
@@ -6148,7 +6162,8 @@ MethodTableBuilder::PlaceMethodImpls()
// (declaration is on this type) or a method desc.
bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
if(hDeclMethod.IsMDMethod())
- { // The declaration is on the type being built
+ {
+ // The declaration is on the type being built
bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
@@ -6157,42 +6172,73 @@ MethodTableBuilder::PlaceMethodImpls()
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef);
}
- // Throws
- PlaceLocalDeclaration(pCurDeclMethod,
- pCurImplMethod,
- slots, // Adds override to the slot and replaced arrays.
- replaced,
- &slotIndex); // Increments count
+ if (IsInterface())
+ {
+ // Throws
+ PlaceInterfaceDeclarationOnInterface(
+ hDeclMethod,
+ pCurImplMethod,
+ slots, // Adds override to the slot and replaced arrays.
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
+ }
+ else
+ {
+ // Throws
+ PlaceLocalDeclarationOnClass(
+ pCurDeclMethod,
+ pCurImplMethod,
+ slots, // Adds override to the slot and replaced arrays.
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
+ }
}
else
{
bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod();
- // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
- if(pCurDeclMethod->GetOwningType()->IsInterface())
+ if (IsInterface())
{
// Throws
- PlaceInterfaceDeclaration(pCurDeclMethod,
- pCurImplMethod,
- slots,
- replaced,
- &slotIndex); // Increments count
+ PlaceInterfaceDeclarationOnInterface(
+ hDeclMethod,
+ pCurImplMethod,
+ slots, // Adds override to the slot and replaced arrays.
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
}
else
{
- // Throws
- PlaceParentDeclaration(pCurDeclMethod,
- pCurImplMethod,
- slots,
- replaced,
- &slotIndex); // Increments count
+ // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
+ if (pCurDeclMethod->GetOwningType()->IsInterface())
+ {
+ // Throws
+ PlaceInterfaceDeclarationOnClass(
+ pCurDeclMethod,
+ pCurImplMethod);
+ }
+ else
+ {
+ // Throws
+ PlaceParentDeclarationOnClass(
+ pCurDeclMethod,
+ pCurImplMethod,
+ slots,
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
+ }
}
}
iEntry++;
if(iEntry == bmtMethodImpl->pIndex)
- { // We hit the end of the list so dump the current data and leave
+ {
+ // We hit the end of the list so dump the current data and leave
WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
break;
}
@@ -6201,7 +6247,8 @@ MethodTableBuilder::PlaceMethodImpls()
bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
if (pNextImplMethod != pCurImplMethod)
- { // If we're moving on to a new body, dump the current data and reset the counter
+ {
+ // If we're moving on to a new body, dump the current data and reset the counter
WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
slotIndex = 0;
}
@@ -6240,20 +6287,32 @@ MethodTableBuilder::WriteMethodImplData(
// Set the size of the info the MethodImpl needs to keep track of.
pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots);
- // Gasp we do a bubble sort. Should change this to a qsort..
- for (DWORD i = 0; i < cSlots; i++)
+ if (!IsInterface())
{
- for (DWORD j = i+1; j < cSlots; j++)
+ // If we are currently builting an interface, the slots here has no meaning and we can skip it
+ // Sort the two arrays in slot index order
+ // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using
+ // binary search later
+ for (DWORD i = 0; i < cSlots; i++)
{
- if (rgSlots[j] < rgSlots[i])
+ int min = i;
+ for (DWORD j = i + 1; j < cSlots; j++)
+ {
+ if (rgSlots[j] < rgSlots[min])
+ {
+ min = j;
+ }
+ }
+
+ if (min != i)
{
MethodDesc * mTmp = rgDeclMD[i].GetValue();
- rgDeclMD[i].SetValue(rgDeclMD[j].GetValue());
- rgDeclMD[j].SetValue(mTmp);
+ rgDeclMD[i].SetValue(rgDeclMD[min].GetValue());
+ rgDeclMD[min].SetValue(mTmp);
DWORD sTmp = rgSlots[i];
- rgSlots[i] = rgSlots[j];
- rgSlots[j] = sTmp;
+ rgSlots[i] = rgSlots[min];
+ rgSlots[min] = sTmp;
}
}
}
@@ -6267,12 +6326,13 @@ MethodTableBuilder::WriteMethodImplData(
//*******************************************************************************
VOID
-MethodTableBuilder::PlaceLocalDeclaration(
+MethodTableBuilder::PlaceLocalDeclarationOnClass(
bmtMDMethod * pDecl,
bmtMDMethod * pImpl,
DWORD * slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD * pSlotIndex)
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
{
CONTRACTL
{
@@ -6327,20 +6387,18 @@ MethodTableBuilder::PlaceLocalDeclaration(
pImpl);
// We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
slots[*pSlotIndex] = pDecl->GetSlotIndex();
replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc());
// increment the counter
(*pSlotIndex)++;
-} // MethodTableBuilder::PlaceLocalDeclaration
+} // MethodTableBuilder::PlaceLocalDeclarationOnClass
//*******************************************************************************
-VOID MethodTableBuilder::PlaceInterfaceDeclaration(
+VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
bmtRTMethod * pDecl,
- bmtMDMethod * pImpl,
- DWORD* slots,
- RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex)
+ bmtMDMethod * pImpl)
{
CONTRACTL {
STANDARD_VM_CHECK;
@@ -6436,16 +6494,60 @@ VOID MethodTableBuilder::PlaceInterfaceDeclaration(
}
}
#endif //_DEBUG
-} // MethodTableBuilder::PlaceInterfaceDeclaration
+} // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
+
+//*******************************************************************************
+VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
+ bmtMethodHandle hDecl,
+ bmtMDMethod *pImpl,
+ DWORD * slots,
+ RelativePointer<MethodDesc *> * replaced,
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
+{
+ CONTRACTL {
+ STANDARD_VM_CHECK;
+ PRECONDITION(CheckPointer(pImpl));
+ PRECONDITION(IsInterface());
+ PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
+ } CONTRACTL_END;
+
+ MethodDesc * pDeclMD = hDecl.GetMethodDesc();
+
+ if (!bmtProp->fNoSanityChecks)
+ {
+ ///////////////////////////////
+ // Verify the signatures match
+
+ MethodImplCompareSignatures(
+ hDecl,
+ bmtMethodHandle(pImpl),
+ IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
+
+ ///////////////////////////////
+ // Validate the method impl.
+
+ TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
+ }
+
+ // We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
+ slots[*pSlotIndex] = hDecl.GetSlotIndex();
+ replaced[*pSlotIndex].SetValue(pDeclMD);
+
+ // increment the counter
+ (*pSlotIndex)++;
+} // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
//*******************************************************************************
VOID
-MethodTableBuilder::PlaceParentDeclaration(
+MethodTableBuilder::PlaceParentDeclarationOnClass(
bmtRTMethod * pDecl,
bmtMDMethod * pImpl,
DWORD * slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD * pSlotIndex)
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
{
CONTRACTL {
STANDARD_VM_CHECK;
@@ -6488,12 +6590,13 @@ MethodTableBuilder::PlaceParentDeclaration(
pImpl);
// We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
slots[*pSlotIndex] = pDeclMD->GetSlot();
replaced[*pSlotIndex].SetValue(pDeclMD);
// increment the counter
(*pSlotIndex)++;
-} // MethodTableBuilder::PlaceParentDeclaration
+} // MethodTableBuilder::PlaceParentDeclarationOnClass
//*******************************************************************************
// This will validate that all interface methods that were matched during
@@ -6527,8 +6630,8 @@ VOID MethodTableBuilder::ValidateInterfaceMethodConstraints()
// If pTargetMT is null, this indicates that the target MethodDesc belongs
// to the current type. Otherwise, the MethodDesc MUST be owned by a parent
// of the type we're building.
- BOOL fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull();
-
+ BOOL fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull();
+
// If the method is owned by a parent, we need to use the parent's module,
// and we must construct the substitution chain all the way up to the parent.
const Substitution *pSubstTgt = NULL;
@@ -10529,6 +10632,45 @@ MethodTableBuilder::SetupMethodTable2(
#pragma warning(pop)
#endif
+// Returns true if there is at least one default implementation for this interface method
+// We don't care about conflicts at this stage in order to avoid impact type load performance
+BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(MethodDesc *pDeclMD)
+{
+ STANDARD_VM_CONTRACT;
+
+ // If the interface method is already non-abstract, we are done
+ if (pDeclMD->IsDefaultInterfaceMethod())
+ return TRUE;
+
+ MethodTable *pDeclMT = pDeclMD->GetMethodTable();
+
+ // Otherwise, traverse the list of interfaces and see if there is at least one override
+ bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
+ for (; !intIt.AtEnd(); intIt.Next())
+ {
+ MethodTable *pIntfMT = intIt->GetInterfaceType()->GetMethodTable();
+ if (pIntfMT->GetClass()->ContainsMethodImpls() && pIntfMT->CanCastToInterface(pDeclMT))
+ {
+ MethodTable::MethodIterator methodIt(pIntfMT);
+ for (; methodIt.IsValid(); methodIt.Next())
+ {
+ MethodDesc *pMD = methodIt.GetMethodDesc();
+ if (pMD->IsMethodImpl())
+ {
+ MethodImpl::Iterator it(pMD);
+ while (it.IsValid())
+ {
+ if (it.GetMethodDesc() == pDeclMD)
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
{
STANDARD_VM_CONTRACT;
@@ -10604,7 +10746,9 @@ void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData
if (it.GetTarget().IsNull())
{
MethodDesc *pMD = it.GetDeclMethodDesc();
- BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
+
+ if (!HasDefaultInterfaceImplementation(pMD))
+ BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
}
}
}
diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h
index a7d7bdd158..fcb10a86fc 100644
--- a/src/vm/methodtablebuilder.h
+++ b/src/vm/methodtablebuilder.h
@@ -2737,32 +2737,42 @@ private:
// --------------------------------------------------------------------------------------------
// Places a methodImpl pair where the decl is declared by the type being built.
VOID
- PlaceLocalDeclaration(
+ PlaceLocalDeclarationOnClass(
bmtMDMethod * pDecl,
bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
// Places a methodImpl pair where the decl is declared by a parent type.
VOID
- PlaceParentDeclaration(
+ PlaceParentDeclarationOnClass(
bmtRTMethod * pDecl,
bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
- // Places a methodImpl pair where the decl is declared by an interface.
+ // Places a methodImpl pair on a class where the decl is declared by an interface.
VOID
- PlaceInterfaceDeclaration(
+ PlaceInterfaceDeclarationOnClass(
bmtRTMethod * pDecl,
- bmtMDMethod * pImpl,
+ bmtMDMethod * pImpl);
+
+ // --------------------------------------------------------------------------------------------
+ // Places a methodImpl pair on an interface where the decl is declared by an interface.
+ VOID
+ PlaceInterfaceDeclarationOnInterface(
+ bmtMethodHandle hDecl,
+ bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
// This will validate that all interface methods that were matched during
@@ -2844,6 +2854,7 @@ private:
VOID HandleGCForValueClasses(
MethodTable **);
+ BOOL HasDefaultInterfaceImplementation(MethodDesc *pIntfMD);
VOID VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData);
VOID CheckForTypeEquivalence(
diff --git a/tests/src/IL.targets b/tests/src/IL.targets
index d1075e53f7..11a82c50eb 100644
--- a/tests/src/IL.targets
+++ b/tests/src/IL.targets
@@ -13,8 +13,7 @@
<PropertyGroup>
<_ShellKeyMarker Condition="'$(RunningOnUnix)' == 'true'">-</_ShellKeyMarker> <!-- Work around ilasm comandline parser bugs... -->
<_ShellKeyMarker Condition="'$(RunningOnUnix)' != 'true'">/</_ShellKeyMarker>
- <_ilasm>ilasm</_ilasm>
- <_ilasm Condition="'$(RunningOnUnix)' == 'true'">$(CoreCLRBinDir)ilasm</_ilasm>
+ <_ilasm>$(CoreCLRBinDir)ilasm</_ilasm>
<_OutputTypeArgument Condition="'$(OutputType)' == 'Library'">$(_ShellKeyMarker)DLL</_OutputTypeArgument>
<_OutputTypeArgument Condition="'$(OutputType)' == 'Exe'">$(_ShellKeyMarker)EXE</_OutputTypeArgument>
<_IlasmSwitches>-QUIET -NOLOGO</_IlasmSwitches>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs
new file mode 100644
index 0000000000..decd7bdd8d
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+
+interface IFoo
+{
+ int Foo(int c);
+}
+
+interface IAdd
+{
+ int Add(int c);
+}
+
+// Only needed for writing IFoo.Foo code
+class IFoo_Impl : IFoo
+{
+ public int Foo(int c)
+ {
+ IAdd adder = (IAdd) this;
+ return adder.Add(c);
+ }
+}
+
+struct FooValue : IFoo, IAdd
+{
+ public int val;
+
+ public int Foo(int c)
+ {
+ val +=c;
+ return val;
+ }
+
+ public int Add(int c)
+ {
+ val +=c;
+ return val;
+ }
+}
+
+interface IHorrible<T>
+{
+ int GetLocalVal();
+ void SetLocalVal(int val);
+ int Horrible();
+}
+
+// Only needed for the default interface implementation
+class IHorrible_Impl<T> : IHorrible<T>
+{
+ public int GetLocalVal() { return 0; }
+ public void SetLocalVal(int val) {}
+ public int Horrible()
+ {
+ int val = GetLocalVal();
+ val++;
+ SetLocalVal(val);
+ return val;
+ }
+}
+
+struct HorribleCase<Z> : IHorrible<IList<Z>>, IHorrible<IEnumerable<Z>>
+{
+ int localVal;
+ public int GetLocalVal() { return localVal; }
+ public void SetLocalVal(int val) { localVal = val; }
+ int IHorrible<IList<Z>>.Horrible() { return ++localVal; }
+
+ // Remove
+ int IHorrible<IEnumerable<Z>>.Horrible() { return ++localVal; }
+}
+
+class HorribleTest
+{
+ public static int Horror<T,U>(T t) where T:IHorrible<U>
+ {
+ return t.Horrible() + t.Horrible();
+ }
+
+ public static void RunTest()
+ {
+ Test.Assert(Horror<HorribleCase<object>,IEnumerable<object>>(new HorribleCase<object>())) == 2, "Fail");
+ Test.Assert(Horror<HorribleCase<object>,IList<object>>(default(HorribleCase<object>)) == 3, "Fail");
+ }
+}
+
+/*
+interface IFoo<T>
+{
+ int Foo(int c);
+}
+
+interface IAdd
+{
+ int Add(int c);
+}
+
+// Only needed for writing IFoo.Foo code
+class IFoo_Impl<T> : IFoo<T>
+{
+ public int Foo(int c)
+ {
+ IAdd adder = (IAdd) this;
+ return adder.Add(c);
+ }
+}
+
+struct FooValue<T> : IFoo<T>, IAdd
+{
+ public int val;
+
+ public int Foo(int c)
+ {
+ val +=c;
+ return val;
+ }
+
+ public int Add(int c)
+ {
+ val +=c;
+ return val;
+ }
+}
+*/
+
+class SimpleConstraintTest
+{
+ public static int CallFoo_WithConstraints<T>(ref T foo, int val) where T : IFoo
+ {
+ return foo.Foo(val);
+ }
+
+ /*
+ public static int CallFoo_WithConstraints<T>(ref T foo, int val) where T : IFoo<object>
+ {
+ return foo.Foo(val);
+ }
+ */
+
+ public static void RunTest()
+ {
+ FooValue foo = new FooValue();
+ foo.val = 10;
+
+ Console.WriteLine("Calling CallFoo_WithConstraints on FooValue - expecting IFoo::Foo");
+ Test.Assert(CallFoo_WithConstraints(ref foo, 10) == 20, "Calling CallFoo_WithConstraints on FooValue");
+
+ Test.Assert(foo.val == 10, "Expecting boxing on CallFoo_WithConstraints");
+ }
+}
+
+class Program
+{
+ public static int Main()
+ {
+ HorribleTest.RunTest();
+ SimpleConstraintTest.RunTest();
+
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il
new file mode 100644
index 0000000000..ef39ba51e1
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il
@@ -0,0 +1,456 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly constrainedcall
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module constrainedcall.exe
+// MVID: {6171EA0F-1009-482D-8EF6-C944886D5D66}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01860000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Foo(int32 c) cil managed
+ {
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (class IAdd V_0,
+ int32 V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: castclass IAdd
+ IL_0007: stloc.0
+ IL_0008: ldloc.0
+ IL_0009: ldarg.1
+ IL_000a: callvirt instance int32 IAdd::Add(int32)
+ IL_000f: stloc.1
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.1
+ IL_0013: ret
+ } // end of method IFoo::Foo
+
+} // end of class IFoo
+
+.class interface private abstract auto ansi IAdd
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 Add(int32 c) cil managed
+ {
+ } // end of method IAdd::Add
+
+} // end of class IAdd
+
+.class private sequential ansi sealed beforefieldinit FooValue
+ extends [mscorlib]System.ValueType
+ implements IFoo,
+ IAdd
+{
+ .field public int32 val
+
+ .method public hidebysig newslot virtual final
+ instance int32 Add(int32 c) cil managed
+ {
+ // Code size 26 (0x1a)
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldarg.0
+ IL_0003: ldfld int32 FooValue::val
+ IL_0008: ldarg.1
+ IL_0009: add
+ IL_000a: stfld int32 FooValue::val
+ IL_000f: ldarg.0
+ IL_0010: ldfld int32 FooValue::val
+ IL_0015: stloc.0
+ IL_0016: br.s IL_0018
+
+ IL_0018: ldloc.0
+ IL_0019: ret
+ } // end of method FooValue::Add
+
+} // end of class FooValue
+
+.class interface private abstract auto ansi IHorrible`1<T>
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 GetLocalVal() cil managed
+ {
+ } // end of method IHorrible`1::GetLocalVal
+
+ .method public hidebysig newslot abstract virtual
+ instance void SetLocalVal(int32 val) cil managed
+ {
+ } // end of method IHorrible`1::SetLocalVal
+
+ .method public hidebysig newslot virtual
+ instance int32 Horrible() cil managed
+ {
+ // Code size 26 (0x1a)
+ .maxstack 2
+ .locals init (int32 V_0,
+ int32 V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: callvirt instance int32 class IHorrible`1<!T>::GetLocalVal()
+ IL_0007: stloc.0
+ IL_0008: ldloc.0
+ IL_0009: ldc.i4.1
+ IL_000a: add
+ IL_000b: stloc.0
+ IL_000c: ldarg.0
+ IL_000d: ldloc.0
+ IL_000e: callvirt instance void class IHorrible`1<!T>::SetLocalVal(int32)
+ IL_0013: nop
+ IL_0014: ldloc.0
+ IL_0015: stloc.1
+ IL_0016: br.s IL_0018
+
+ IL_0018: ldloc.1
+ IL_0019: ret
+ } // end of method IHorrible`1::Horrible
+
+} // end of class IHorrible`1
+
+.class private sequential ansi sealed beforefieldinit HorribleCase`1<Z>
+ extends [mscorlib]System.ValueType
+ implements class IHorrible`1<class [mscorlib]System.Collections.Generic.IList`1<!Z>>,
+ class IHorrible`1<class [mscorlib]System.Collections.Generic.IEnumerable`1<!Z>>
+{
+ .field private int32 localVal
+ .method public hidebysig newslot virtual final
+ instance int32 GetLocalVal() cil managed
+ {
+ // Code size 12 (0xc)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldfld int32 valuetype HorribleCase`1<!Z>::localVal
+ IL_0007: stloc.0
+ IL_0008: br.s IL_000a
+
+ IL_000a: ldloc.0
+ IL_000b: ret
+ } // end of method HorribleCase`1::GetLocalVal
+
+ .method public hidebysig newslot virtual final
+ instance void SetLocalVal(int32 val) cil managed
+ {
+ // Code size 9 (0x9)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldarg.1
+ IL_0003: stfld int32 valuetype HorribleCase`1<!Z>::localVal
+ IL_0008: ret
+ } // end of method HorribleCase`1::SetLocalVal
+
+ .method private hidebysig newslot virtual final
+ instance int32 'IHorrible<System.Collections.Generic.IList<Z>>.Horrible'() cil managed
+ {
+ .override method instance int32 class IHorrible`1<class [mscorlib]System.Collections.Generic.IList`1<!Z>>::Horrible()
+ // Code size 23 (0x17)
+ .maxstack 3
+ .locals init (int32 V_0,
+ int32 V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldarg.0
+ IL_0003: ldfld int32 valuetype HorribleCase`1<!Z>::localVal
+ IL_0008: ldc.i4.1
+ IL_0009: add
+ IL_000a: stloc.0
+ IL_000b: ldloc.0
+ IL_000c: stfld int32 valuetype HorribleCase`1<!Z>::localVal
+ IL_0011: ldloc.0
+ IL_0012: stloc.1
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.1
+ IL_0016: ret
+ } // end of method HorribleCase`1::'IHorrible<System.Collections.Generic.IList<Z>>.Horrible'
+} // end of class HorribleCase`1
+
+.class private auto ansi beforefieldinit HorribleTest
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Horror<(class IHorrible`1<!!U>) T,U>(!!T t) cil managed
+ {
+ // Code size 33 (0x21)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarga.s t
+ IL_0003: constrained. !!T
+ IL_0009: callvirt instance int32 class IHorrible`1<!!U>::Horrible()
+ IL_000e: ldarga.s t
+ IL_0010: constrained. !!T
+ IL_0016: callvirt instance int32 class IHorrible`1<!!U>::Horrible()
+ IL_001b: add
+ IL_001c: stloc.0
+ IL_001d: br.s IL_001f
+
+ IL_001f: ldloc.0
+ IL_0020: ret
+ } // end of method HorribleTest::Horror
+
+ .method public hidebysig static void RunTest() cil managed
+ {
+ // Code size 58 (0x3a)
+ .maxstack 2
+ .locals init (valuetype HorribleCase`1<object> V_0)
+ IL_0000: nop
+ IL_0001: ldloca.s V_0
+ IL_0003: initobj valuetype HorribleCase`1<object>
+ IL_0009: ldloc.0
+ IL_000a: call int32 HorribleTest::Horror<valuetype HorribleCase`1<object>,class [mscorlib]System.Collections.Generic.IEnumerable`1<object>>(!!0)
+ IL_000f: ldc.i4.3
+ IL_0010: ceq
+ IL_0012: ldstr "Fail"
+ IL_0017: call void Test::Assert(bool,
+ string)
+ IL_001c: nop
+ IL_001d: ldloca.s V_0
+ IL_001f: initobj valuetype HorribleCase`1<object>
+ IL_0025: ldloc.0
+ IL_0026: call int32 HorribleTest::Horror<valuetype HorribleCase`1<object>,class [mscorlib]System.Collections.Generic.IList`1<object>>(!!0)
+ IL_002b: ldc.i4.0
+ IL_002c: ceq
+ IL_002e: ldstr "Fail"
+ IL_0033: call void Test::Assert(bool,
+ string)
+ IL_0038: nop
+ IL_0039: ret
+ } // end of method HorribleTest::RunTest
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method HorribleTest::.ctor
+
+} // end of class HorribleTest
+
+.class private auto ansi beforefieldinit SimpleConstraintTest
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 CallFoo_WithConstraints<(IFoo) T>(!!T& foo,
+ int32 val) cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldarg.1
+ IL_0003: constrained. !!T
+ IL_0009: callvirt instance int32 IFoo::Foo(int32)
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method SimpleConstraintTest::CallFoo_WithConstraints
+
+ .method public hidebysig static void RunTest() cil managed
+ {
+ // Code size 75 (0x4b)
+ .maxstack 2
+ .locals init (valuetype FooValue V_0)
+ IL_0000: nop
+ IL_0001: ldloca.s V_0
+ IL_0003: initobj FooValue
+ IL_0009: ldloca.s V_0
+ IL_000b: ldc.i4.s 10
+ IL_000d: stfld int32 FooValue::val
+ IL_0012: ldstr "Calling CallFoo_WithConstraints on FooValue - expe"
+ + "cting IFoo::Foo"
+ IL_0017: call void [mscorlib]System.Console::WriteLine(string)
+ IL_001c: nop
+ IL_001d: ldloca.s V_0
+ IL_001f: ldc.i4.s 10
+ IL_0021: call int32 SimpleConstraintTest::CallFoo_WithConstraints<valuetype FooValue>(!!0&,
+ int32)
+ IL_0026: ldc.i4.s 20
+ IL_0028: ceq
+ IL_002a: ldstr "Calling CallFoo_WithConstraints on FooValue"
+ IL_002f: call void Test::Assert(bool,
+ string)
+ IL_0034: nop
+ IL_0035: ldloc.0
+ IL_0036: ldfld int32 FooValue::val
+ IL_003b: ldc.i4.s 10
+ IL_003d: ceq
+ IL_003f: ldstr "Expecting boxing on CallFoo_WithConstraints"
+ IL_0044: call void Test::Assert(bool,
+ string)
+ IL_0049: nop
+ IL_004a: ret
+ } // end of method SimpleConstraintTest::RunTest
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method SimpleConstraintTest::.ctor
+
+} // end of class SimpleConstraintTest
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 23 (0x17)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: call void HorribleTest::RunTest()
+ IL_0006: nop
+ IL_0007: call void SimpleConstraintTest::RunTest()
+ IL_000c: nop
+ IL_000d: call int32 Test::Ret()
+ IL_0012: stloc.0
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.0
+ IL_0016: ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file constrainedcall.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj
new file mode 100644
index 0000000000..e170b2b467
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>constrainedcall</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="constrainedcall.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs
new file mode 100644
index 0000000000..3ff3760aa3
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs
@@ -0,0 +1,255 @@
+using System;
+
+interface IFoo
+{
+ int Foo(int a);
+}
+
+class IFoo_Impl
+{
+ int Foo(int a)
+ {
+ return a;
+ }
+}
+
+interface IFoo2 : IFoo
+{
+}
+
+class IFoo2_Impl : IFoo
+{
+ int IFoo.Foo(int a)
+ {
+ Console.WriteLine("At IFoo2.Foo");
+ return a + 1;
+ }
+}
+
+interface IFooEx : IFoo
+{
+}
+
+class IFooEx_Impl : IFoo
+{
+ int IFoo.Foo(int a)
+ {
+ Console.WriteLine("At IFooEx.Foo");
+ return a + 2;
+ }
+}
+
+class FooClass : IFoo2, IFooEx
+{
+ // Dummy
+ public int Foo(int a)
+ {
+ return 0;
+ }
+}
+
+interface I1
+{
+ int Func(int a);
+}
+
+interface I2 : I1
+{
+ // int I1.Func(int a) { return a + 2; }
+}
+
+interface I3 : I1
+{
+ // int I1.Func(int a) { return a + 3; }
+}
+
+interface I4 : I2, I3
+{
+ // int I1.Func(int a) { return a + 4; }
+}
+
+class I4Class : I4
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 4;
+ }
+}
+
+interface I5: I1
+{
+ // int I1.Func(int a) { return a + 5; }
+}
+
+interface I6: I1
+{
+ // int I1.Func(int a) { return a + 6; }
+}
+
+interface I7: I5, I6
+{
+ // int I1.Func(int a) { return a + 7; }
+}
+
+interface I8: I4, I7
+{
+ // int I1.Func(int a) { return a + 8; }
+}
+
+class I47Class: I4, I7
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 8;
+ }
+
+}
+
+class I8Class: I8
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 8;
+ }
+}
+
+interface GI1<T>
+{
+ int Func<S>(out Type[] types);
+}
+
+interface GI2<T> : GI1<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 2; }
+
+}
+
+interface GI3<T> : GI1<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 3; }
+}
+
+interface GI4<T> : GI2<T>, GI3<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
+class GI23Class<T>: GI2<T>, GI3<T>
+{
+ // @REMOVE
+ int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
+class GI4Class<T>: GI4<T>
+{
+ // @REMOVE
+ int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
+class Program
+{
+ public static void Negative()
+ {
+ FooClass fooObj = new FooClass();
+ IFoo foo = (IFoo) fooObj;
+
+ Console.WriteLine("Calling IFoo.Foo on Foo - expecting exception.");
+ try
+ {
+ foo.Foo(10);
+ Test.Assert(false, "Expecting exception on Foo");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
+ }
+
+ I47Class i47Class = new I47Class();
+ I1 i1 = (I1) i47Class;
+ Console.WriteLine("Calling I1.Func on I47Class - expecting exception");
+ try
+ {
+ i1.Func(10);
+ Test.Assert(false, "Expecting exception on I47Class");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
+ }
+
+ var gi23Class = new GI23Class<object>();
+ GI1<object> gi1 = (GI1<object>) gi23Class;
+ Console.WriteLine("Calling GI1<T>.Func on GI23Class<S> - expecting exception");
+ try
+ {
+ Type[] types;
+ gi1.Func<string>(out types);
+ Test.Assert(false, "Expecting exception on GI23Class");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
+ }
+ }
+
+ public static void Positive()
+ {
+ Console.WriteLine("Calling I1.Func on I4Class - expecting I4.Func");
+
+ I4Class i4Class = new I4Class();
+ I1 i1 = (I1) i4Class;
+ Test.Assert(i1.Func(10) == 14, "Expecting I1.Func to land on I4.Func");
+
+ Console.WriteLine("Calling I1.Func on I8Class - expecting I8.Func");
+
+ I8Class i8Class = new I8Class();
+ i1 = (I1) i8Class;
+ Test.Assert(i1.Func(10) == 18, "Expecting I1.Func to land on I8.Func");
+
+ Console.WriteLine("Calling GI1.Func on GI4Class<object> - expecting GI4.Func<S>");
+
+ var gi4Class = new GI4Class<object>();
+ Type[] types;
+ var gi1 = (GI1<object>) gi4Class;
+ Test.Assert(gi1.Func<string>(out types) == 4, "Expecting GI1<T>.Func to land on GII4<T>.Func<S>");
+ Test.Assert(types[0] == typeof(object), "T must be object");
+ Test.Assert(types[1] == typeof(string), "S must be string");
+ }
+
+ public static int Main()
+ {
+ Negative();
+ Positive();
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il
new file mode 100644
index 0000000000..4173bc6aea
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il
@@ -0,0 +1,944 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly diamondshape
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module diamondshape.exe
+// MVID: {25B467F3-D284-4DB6-BAD4-C7EAC75CF064}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x010B0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Foo(int32 a) cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.1
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ } // end of method IFoo::Foo
+
+} // end of class IFoo
+
+.class interface private abstract auto ansi IFoo2
+ implements IFoo
+{
+ .method public hidebysig newslot virtual final
+ instance int32 Foo(int32 a) cil managed
+ {
+ .override IFoo::Foo
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo2.Foo"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.1
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method IFoo2::IFoo.Foo
+
+} // end of class IFoo2
+
+.class interface private abstract auto ansi IFooEx
+ implements IFoo
+{
+ .method public hidebysig newslot virtual final
+ instance int32 IFoo.Foo(int32 a) cil managed
+ {
+ .override IFoo::Foo
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooEx.Foo"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.2
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method IFooEx::IFoo.Foo
+} // end of class IFooEx
+
+.class private auto ansi beforefieldinit FooClass
+ extends [mscorlib]System.Object
+ implements IFoo2,
+ IFoo,
+ IFooEx
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooClass::.ctor
+
+} // end of class FooClass
+
+.class interface private abstract auto ansi I1
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 Func(int32 a) cil managed
+ {
+ } // end of method I1::Func
+
+} // end of class I1
+
+.class interface private abstract auto ansi I2
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I2.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.2
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I2::I1.Func
+} // end of class I2
+
+.class interface private abstract auto ansi I3
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I3.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.3
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I3::I1.Func
+} // end of class I3
+
+.class interface private abstract auto ansi I4
+ implements I2,
+ I1,
+ I3
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I4.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.4
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I4::I1.Func
+} // end of class I4
+
+.class private auto ansi beforefieldinit I4Class
+ extends [mscorlib]System.Object
+ implements I4,
+ I2,
+ I1,
+ I3
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I4Class::.ctor
+
+} // end of class I4Class
+
+.class interface private abstract auto ansi I5
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I5.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.5
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I5::I1.Func
+} // end of class I5
+
+.class interface private abstract auto ansi I6
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I6.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.6
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I6::I1.Func
+} // end of class I6
+
+.class interface private abstract auto ansi I7
+ implements I5,
+ I1,
+ I6
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I7.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.7
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I7::I1.Func
+} // end of class I7
+
+.class interface private abstract auto ansi I8
+ implements I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I8.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.8
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I8::I1.Func
+} // end of class I8
+
+.class private auto ansi beforefieldinit I47Class
+ extends [mscorlib]System.Object
+ implements I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I47Class::.ctor
+
+} // end of class I47Class
+
+.class private auto ansi beforefieldinit I8Class
+ extends [mscorlib]System.Object
+ implements I8,
+ I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I8Class::.ctor
+
+} // end of class I8Class
+
+.class interface private abstract auto ansi GI1`1<T>
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 Func<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ } // end of method GI1`1::'GI1<T>.Func'
+
+} // end of class GI1`1
+
+.class interface private abstract auto ansi GI2`1<T>
+ implements class GI1`1<!T>
+{
+.method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI2"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.2
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method G2`1::'GI1<T>.Func'
+} // end of class GI2`1
+
+.class interface private abstract auto ansi GI3`1<T>
+ implements class GI1`1<!T>
+{
+.method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI3"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.3
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method GI3`1::'GI1<T>.Func'
+} // end of class GI3`1
+
+.class interface private abstract auto ansi GI4`1<T>
+ implements class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI4"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.4
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method GI4`1::'GI1<T>.Func'
+} // end of class GI4`1
+
+.class private auto ansi beforefieldinit GI23Class`1<T>
+ extends [mscorlib]System.Object
+ implements class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method GI23Class`1::.ctor
+
+} // end of class GI23Class`1
+
+.class private auto ansi beforefieldinit GI4Class`1<T>
+ extends [mscorlib]System.Object
+ implements class GI4`1<!T>,
+ class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method GI4Class`1::.ctor
+
+} // end of class GI4Class`1
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Negative() cil managed
+ {
+ // Code size 225 (0xe1)
+ .maxstack 2
+ .locals init (class FooClass V_0,
+ class IFoo V_1,
+ class I47Class V_2,
+ class I1 V_3,
+ class GI23Class`1<object> V_4,
+ class GI1`1<object> V_5,
+ class [mscorlib]System.Exception V_6,
+ class [mscorlib]System.Exception V_7,
+ class [mscorlib]System.Type[] V_8,
+ class [mscorlib]System.Exception V_9)
+ IL_0000: nop
+ IL_0001: newobj instance void FooClass::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldstr "Calling IFoo.Foo on Foo - expecting exception."
+ IL_000e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0013: nop
+ .try
+ {
+ IL_0014: nop
+ IL_0015: ldloc.1
+ IL_0016: ldc.i4.s 10
+ IL_0018: callvirt instance int32 IFoo::Foo(int32)
+ IL_001d: pop
+ IL_001e: ldc.i4.0
+ IL_001f: ldstr "Expecting exception on Foo"
+ IL_0024: call void Test::Assert(bool,
+ string)
+ IL_0029: nop
+ IL_002a: nop
+ IL_002b: leave.s IL_004a
+
+ } // end .try
+ catch [mscorlib]System.Exception
+ {
+ IL_002d: stloc.s V_6
+ IL_002f: nop
+ IL_0030: ldstr "Exception caught: "
+ IL_0035: ldloc.s V_6
+ IL_0037: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_003c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0041: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0046: nop
+ IL_0047: nop
+ IL_0048: leave.s IL_004a
+
+ } // end handler
+ IL_004a: newobj instance void I47Class::.ctor()
+ IL_004f: stloc.2
+ IL_0050: ldloc.2
+ IL_0051: stloc.3
+ IL_0052: ldstr "Calling I1.Func on I47Class - expecting exception"
+ IL_0057: call void [mscorlib]System.Console::WriteLine(string)
+ IL_005c: nop
+ .try
+ {
+ IL_005d: nop
+ IL_005e: ldloc.3
+ IL_005f: ldc.i4.s 10
+ IL_0061: callvirt instance int32 I1::Func(int32)
+ IL_0066: pop
+ IL_0067: ldc.i4.0
+ IL_0068: ldstr "Expecting exception on I47Class"
+ IL_006d: call void Test::Assert(bool,
+ string)
+ IL_0072: nop
+ IL_0073: nop
+ IL_0074: leave.s IL_0093
+
+ } // end .try
+ catch [mscorlib]System.Exception
+ {
+ IL_0076: stloc.s V_7
+ IL_0078: nop
+ IL_0079: ldstr "Exception caught: "
+ IL_007e: ldloc.s V_7
+ IL_0080: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_0085: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_008a: call void [mscorlib]System.Console::WriteLine(string)
+ IL_008f: nop
+ IL_0090: nop
+ IL_0091: leave.s IL_0093
+
+ } // end handler
+ IL_0093: newobj instance void class GI23Class`1<object>::.ctor()
+ IL_0098: stloc.s V_4
+ IL_009a: ldloc.s V_4
+ IL_009c: stloc.s V_5
+ IL_009e: ldstr "Calling GI1<T>.Func on GI23Class<S> - expecting ex"
+ + "ception"
+ IL_00a3: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00a8: nop
+ .try
+ {
+ IL_00a9: nop
+ IL_00aa: ldloc.s V_5
+ IL_00ac: ldloca.s V_8
+ IL_00ae: callvirt instance int32 class GI1`1<object>::Func<string>(class [mscorlib]System.Type[]&)
+ IL_00b3: pop
+ IL_00b4: ldc.i4.0
+ IL_00b5: ldstr "Expecting exception on GI23Class"
+ IL_00ba: call void Test::Assert(bool,
+ string)
+ IL_00bf: nop
+ IL_00c0: nop
+ IL_00c1: leave.s IL_00e0
+
+ } // end .try
+ catch [mscorlib]System.Exception
+ {
+ IL_00c3: stloc.s V_9
+ IL_00c5: nop
+ IL_00c6: ldstr "Exception caught: "
+ IL_00cb: ldloc.s V_9
+ IL_00cd: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_00d2: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_00d7: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00dc: nop
+ IL_00dd: nop
+ IL_00de: leave.s IL_00e0
+
+ } // end handler
+ IL_00e0: ret
+ } // end of method Program::Negative
+
+ .method public hidebysig static void Positive() cil managed
+ {
+ // Code size 189 (0xbd)
+ .maxstack 2
+ .locals init (class I4Class V_0,
+ class I1 V_1,
+ class I8Class V_2,
+ class GI4Class`1<object> V_3,
+ class [mscorlib]System.Type[] V_4,
+ class GI1`1<object> V_5)
+ IL_0000: nop
+ IL_0001: ldstr "Calling I1.Func on I4Class - expecting I4.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: newobj instance void I4Class::.ctor()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: stloc.1
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.s 10
+ IL_0017: callvirt instance int32 I1::Func(int32)
+ IL_001c: ldc.i4.s 14
+ IL_001e: ceq
+ IL_0020: ldstr "Expecting I1.Func to land on I4.Func"
+ IL_0025: call void Test::Assert(bool,
+ string)
+ IL_002a: nop
+ IL_002b: ldstr "Calling I1.Func on I8Class - expecting I8.Func"
+ IL_0030: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0035: nop
+ IL_0036: newobj instance void I8Class::.ctor()
+ IL_003b: stloc.2
+ IL_003c: ldloc.2
+ IL_003d: stloc.1
+ IL_003e: ldloc.1
+ IL_003f: ldc.i4.s 10
+ IL_0041: callvirt instance int32 I1::Func(int32)
+ IL_0046: ldc.i4.s 18
+ IL_0048: ceq
+ IL_004a: ldstr "Expecting I1.Func to land on I8.Func"
+ IL_004f: call void Test::Assert(bool,
+ string)
+ IL_0054: nop
+ IL_0055: ldstr "Calling GI1.Func on GI4Class<object> - expecting G"
+ + "I4.Func<S>"
+ IL_005a: call void [mscorlib]System.Console::WriteLine(string)
+ IL_005f: nop
+ IL_0060: newobj instance void class GI4Class`1<object>::.ctor()
+ IL_0065: stloc.3
+ IL_0066: ldloc.3
+ IL_0067: stloc.s V_5
+ IL_0069: ldloc.s V_5
+ IL_006b: ldloca.s V_4
+ IL_006d: callvirt instance int32 class GI1`1<object>::Func<string>(class [mscorlib]System.Type[]&)
+ IL_0072: ldc.i4.4
+ IL_0073: ceq
+ IL_0075: ldstr "Expecting GI1<T>.Func to land on GII4<T>.Func<S>"
+ IL_007a: call void Test::Assert(bool,
+ string)
+ IL_007f: nop
+ IL_0080: ldloc.s V_4
+ IL_0082: ldc.i4.0
+ IL_0083: ldelem.ref
+ IL_0084: ldtoken [mscorlib]System.Object
+ IL_0089: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_008e: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0093: ldstr "T must be object"
+ IL_0098: call void Test::Assert(bool,
+ string)
+ IL_009d: nop
+ IL_009e: ldloc.s V_4
+ IL_00a0: ldc.i4.1
+ IL_00a1: ldelem.ref
+ IL_00a2: ldtoken [mscorlib]System.String
+ IL_00a7: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_00ac: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_00b1: ldstr "S must be string"
+ IL_00b6: call void Test::Assert(bool,
+ string)
+ IL_00bb: nop
+ IL_00bc: ret
+ } // end of method Program::Positive
+
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 23 (0x17)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: call void Program::Negative()
+ IL_0006: nop
+ IL_0007: call void Program::Positive()
+ IL_000c: nop
+ IL_000d: call int32 Test::Ret()
+ IL_0012: stloc.0
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.0
+ IL_0016: ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file diamondshape.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj
new file mode 100644
index 0000000000..34df037a0d
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>diamondshape</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="diamondshape.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs
new file mode 100644
index 0000000000..ca4936b270
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+interface IFoo
+{
+ Type Foo<T>();
+}
+
+interface IBar<T>
+{
+ Type Bar1<P>();
+ Type Bar2<K>();
+ void Bar3<P, K>(out Type t, out Type u);
+}
+
+class FooBar<V> : IFoo, IBar<V>
+{
+ public Type Foo<T>()
+ {
+ Console.WriteLine("At IFoo<T>::Foo<T>: TypeOf(T) = {0}", typeof(T));
+ return typeof(T);
+ }
+
+ public Type Bar1<P>()
+ {
+ Console.WriteLine("At IBar<T>::Foo<P>: TypeOf(P) = {0}", typeof(P));
+ return typeof(P);
+ }
+
+ public Type Bar2<K>()
+ {
+ Console.WriteLine("At IBar<T>::Bar2<K>: TypeOf(K) = {0}", typeof(K));
+ return typeof(K);
+ }
+
+ public void Bar3<P, K>(out Type t, out Type u)
+ {
+ Console.WriteLine("At IBar<T>::Bar3<P, K>: TypeOf(P) = {0}, TypeOf(K) = {1}", typeof(P), typeof(K));
+ t = typeof(P);
+ u = typeof(K);
+ }
+}
+
+
+class Program
+{
+ static int Main(string[] args)
+ {
+ FooBar<object> fooBar = new FooBar<object>();
+ IFoo foo = (IFoo) fooBar;
+ IBar<object> bar = (IBar<object>) fooBar;
+
+ Console.WriteLine("Calling IFoo.Foo<String> on FooBar<Object> - expecting IFoo::Foo<string>() returning typeof(string)");
+ Test.Assert(foo.Foo<string>() == typeof(string), "Calling IFoo.Foo<String> on FooBar<Object>");
+
+ Console.WriteLine("Calling IBar.Bar1<String> on FooBar<object> - expecting bar.Bar1<string>() returning typeof(string)");
+ Test.Assert(bar.Bar1<string>() == typeof(string), "Calling IBar.Bar1<String> on FooBar<object>");
+
+ Console.WriteLine("Calling IBar.Bar2<String[]> on FooBar<object> - expecting bar.Bar2<string[]>() returning typeof(string[])");
+ Test.Assert(bar.Bar2<string[]>() == typeof(string[]), "Calling IBar.Bar2<String[]> on FooBar<object>");
+
+ Type p, k;
+ Console.WriteLine("Calling IBar.Bar3<String, String[]> - expecting bar.Bar3<string>() returning typeof(string), typeof(string[])");
+ bar.Bar3<string, string[]>(out p, out k);
+ Test.Assert(p == typeof(string) && k == typeof(string[]), "Calling IBar.Bar3<String, String[]>");
+
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass ? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il
new file mode 100644
index 0000000000..3a3204da41
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il
@@ -0,0 +1,357 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly genericmethods
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module genericmethods.exe
+// MVID: {62CAFB9A-4CDB-4A62-8A4F-DC7648609070}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01790000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IFoo
+{
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.Type
+ Foo<T>() cil managed
+ {
+ // Code size 37 (0x25)
+ .maxstack 2
+ .locals init (class [mscorlib]System.Type V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo<T>::Foo<T>: TypeOf(T) = {0}"
+ IL_0006: ldtoken !!T
+ IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0010: call void [mscorlib]System.Console::WriteLine(string,
+ object)
+ IL_0015: nop
+ IL_0016: ldtoken !!T
+ IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0020: stloc.0
+ IL_0021: br.s IL_0023
+
+ IL_0023: ldloc.0
+ IL_0024: ret
+ } // end of method IFoo::Foo
+
+} // end of class IFoo
+
+.class interface private abstract auto ansi IBar`1<T>
+{
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.Type
+ Bar1<P>() cil managed
+ {
+ // Code size 37 (0x25)
+ .maxstack 2
+ .locals init (class [mscorlib]System.Type V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar<T>::Foo<P>: TypeOf(P) = {0}"
+ IL_0006: ldtoken !!P
+ IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0010: call void [mscorlib]System.Console::WriteLine(string,
+ object)
+ IL_0015: nop
+ IL_0016: ldtoken !!P
+ IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0020: stloc.0
+ IL_0021: br.s IL_0023
+
+ IL_0023: ldloc.0
+ IL_0024: ret
+ } // end of method IBar`1::Bar1
+
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.Type
+ Bar2<K>() cil managed
+ {
+ // Code size 37 (0x25)
+ .maxstack 2
+ .locals init (class [mscorlib]System.Type V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar<T>::Bar2<K>: TypeOf(K) = {0}"
+ IL_0006: ldtoken !!K
+ IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0010: call void [mscorlib]System.Console::WriteLine(string,
+ object)
+ IL_0015: nop
+ IL_0016: ldtoken !!K
+ IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0020: stloc.0
+ IL_0021: br.s IL_0023
+
+ IL_0023: ldloc.0
+ IL_0024: ret
+ } // end of method IBar`1::Bar2
+
+ .method public hidebysig newslot virtual
+ instance void Bar3<P,K>([out] class [mscorlib]System.Type& t,
+ [out] class [mscorlib]System.Type& u) cil managed
+ {
+ // Code size 57 (0x39)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ldstr "At IBar<T>::Bar3<P, K>: TypeOf(P) = {0}, TypeOf(K)"
+ + " = {1}"
+ IL_0006: ldtoken !!P
+ IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0010: ldtoken !!K
+ IL_0015: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_001a: call void [mscorlib]System.Console::WriteLine(string,
+ object,
+ object)
+ IL_001f: nop
+ IL_0020: ldarg.1
+ IL_0021: ldtoken !!P
+ IL_0026: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_002b: stind.ref
+ IL_002c: ldarg.2
+ IL_002d: ldtoken !!K
+ IL_0032: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0037: stind.ref
+ IL_0038: ret
+ } // end of method IBar`1::Bar3
+
+} // end of class IBar`1
+
+.class private auto ansi beforefieldinit FooBar`1<V>
+ extends [mscorlib]System.Object
+ implements IFoo,
+ class IBar`1<!V>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooBar`1::.ctor
+
+} // end of class FooBar`1
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method private hidebysig static int32
+ Main(string[] args) cil managed
+ {
+ .entrypoint
+ // Code size 223 (0xdf)
+ .maxstack 3
+ .locals init (class FooBar`1<object> V_0,
+ class IFoo V_1,
+ class IBar`1<object> V_2,
+ class [mscorlib]System.Type V_3,
+ class [mscorlib]System.Type V_4,
+ int32 V_5)
+ IL_0000: nop
+ IL_0001: newobj instance void class FooBar`1<object>::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldloc.0
+ IL_000a: stloc.2
+ IL_000b: ldstr "Calling IFoo.Foo<String> on FooBar<Object> - expec"
+ + "ting IFoo::Foo<string>() returning typeof(string)"
+ IL_0010: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0015: nop
+ IL_0016: ldloc.1
+ IL_0017: callvirt instance class [mscorlib]System.Type IFoo::Foo<string>()
+ IL_001c: ldtoken [mscorlib]System.String
+ IL_0021: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0026: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_002b: ldstr "Calling IFoo.Foo<String> on FooBar<Object>"
+ IL_0030: call void Test::Assert(bool,
+ string)
+ IL_0035: nop
+ IL_0036: ldstr "Calling IBar.Bar1<String> on FooBar<object> - expe"
+ + "cting bar.Bar1<string>() returning typeof(string)"
+ IL_003b: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0040: nop
+ IL_0041: ldloc.2
+ IL_0042: callvirt instance class [mscorlib]System.Type class IBar`1<object>::Bar1<string>()
+ IL_0047: ldtoken [mscorlib]System.String
+ IL_004c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0051: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0056: ldstr "Calling IBar.Bar1<String> on FooBar<object>"
+ IL_005b: call void Test::Assert(bool,
+ string)
+ IL_0060: nop
+ IL_0061: ldstr "Calling IBar.Bar2<String[]> on FooBar<object> - ex"
+ + "pecting bar.Bar2<string[]>() returning typeof(string[])"
+ IL_0066: call void [mscorlib]System.Console::WriteLine(string)
+ IL_006b: nop
+ IL_006c: ldloc.2
+ IL_006d: callvirt instance class [mscorlib]System.Type class IBar`1<object>::Bar2<string[]>()
+ IL_0072: ldtoken string[]
+ IL_0077: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_007c: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0081: ldstr "Calling IBar.Bar2<String[]> on FooBar<object>"
+ IL_0086: call void Test::Assert(bool,
+ string)
+ IL_008b: nop
+ IL_008c: ldstr "Calling IBar.Bar3<String, String[]> - expecting ba"
+ + "r.Bar3<string>() returning typeof(string), typeof(string[])"
+ IL_0091: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0096: nop
+ IL_0097: ldloc.2
+ IL_0098: ldloca.s V_3
+ IL_009a: ldloca.s V_4
+ IL_009c: callvirt instance void class IBar`1<object>::Bar3<string,string[]>(class [mscorlib]System.Type&,
+ class [mscorlib]System.Type&)
+ IL_00a1: nop
+ IL_00a2: ldloc.3
+ IL_00a3: ldtoken [mscorlib]System.String
+ IL_00a8: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_00ad: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_00b2: brfalse.s IL_00c7
+
+ IL_00b4: ldloc.s V_4
+ IL_00b6: ldtoken string[]
+ IL_00bb: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_00c0: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_00c5: br.s IL_00c8
+
+ IL_00c7: ldc.i4.0
+ IL_00c8: ldstr "Calling IBar.Bar3<String, String[]>"
+ IL_00cd: call void Test::Assert(bool,
+ string)
+ IL_00d2: nop
+ IL_00d3: call int32 Test::Ret()
+ IL_00d8: stloc.s V_5
+ IL_00da: br.s IL_00dc
+
+ IL_00dc: ldloc.s V_5
+ IL_00de: ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file genericmethods.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj
new file mode 100644
index 0000000000..909dbe94dc
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>genericmethods</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="genericmethods.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs
new file mode 100755
index 0000000000..0d4c119453
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs
@@ -0,0 +1,316 @@
+using System;
+
+interface IFoo
+{
+ int Foo1(int a); // { return a + 1 };
+ int Foo2(int a); // { return a + 2 };
+ int Foo3(int a);
+ int Foo4(int a);
+ int Foo5(int a);
+ int Foo6(int a);
+ int Foo7(int a);
+ int Foo8(int a);
+ int Foo9(int a);
+}
+
+interface IBar : IFoo
+{
+ // @OVERRIDE
+ // IFoo.Foo1/2/3/4/5
+
+ int Bar1(int b); // { return a + 11; }
+ int Bar2(int b); // { return a + 22; }
+ int Bar3(int b); // { return a + 33; }
+ int Bar4(int b);
+ int Bar5(int b);
+ int Bar6(int b);
+ int Bar7(int b);
+ int Bar8(int b);
+ int Bar9(int b);
+}
+
+interface IBlah : IBar
+{
+ // @OVERRIDE IFoo.Foo6/7/8/9
+ // @OVERRIDE IBar.Bar6/7/8/9
+ int Blah1(int c);
+ int Blah2(int c);
+ int Blah3(int c);
+}
+
+class IBarImpl : IBar
+{
+ // @REMOVE all implementation
+ int IFoo.Foo1(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 10;
+ }
+
+ int IFoo.Foo2(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 20;
+ }
+ int IFoo.Foo3(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 30;
+ }
+ int IFoo.Foo4(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 40;
+ }
+ int IFoo.Foo5(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 50;
+ }
+ int IFoo.Foo6(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 60;
+ }
+ int IFoo.Foo7(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 70;
+ }
+ int IFoo.Foo8(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 80;
+ }
+ int IFoo.Foo9(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 19;
+ }
+
+ int IBar.Bar1(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 110;
+ }
+
+ int IBar.Bar2(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 220;
+ }
+ int IBar.Bar3(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 330;
+ }
+ int IBar.Bar4(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 440;
+ }
+ int IBar.Bar5(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 550;
+ }
+ int IBar.Bar6(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 660;
+ }
+ int IBar.Bar7(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 770;
+ }
+ int IBar.Bar8(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 880;
+ }
+ int IBar.Bar9(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 990;
+ }
+}
+
+class IBlahImpl : IBarImpl, IBlah
+{
+ // @REMOVE all implementation
+ // @OVERRIDE IBlah2/3 with + 2220/3330
+ int IBlah.Blah1(int c)
+ {
+ Console.WriteLine("At IBlah.Blah1");
+ return c+111;
+ }
+
+ int IBlah.Blah2(int c)
+ {
+ Console.WriteLine("At IBlah.Blah2");
+ return c+222;
+ }
+
+ int IBlah.Blah3(int c)
+ {
+ Console.WriteLine("At IBlah.Blah3");
+ return c+333;
+ }
+}
+
+interface IFooBarBlah : IFoo, IBar, IBlah
+{
+ // FooBarBlah1 .override IFoo.Foo1/IBar.Bar1/IBlah.Blah1 return 1+11111
+ // FooBarBlah2 .override IFoo.Foo2/IBar.Bar2/IBlah.Blah2 return i+22222
+ // FooBarBLah345 .override IFoo.Foo345/IBar.Bar345/IBlah.Blah3 return i+33333
+}
+
+class FooBarBlahImpl :
+ IBlahImpl, // @REMOVE
+ IFooBarBlah
+{
+
+}
+
+class Program
+{
+ public static int Main()
+ {
+ SingleOverride();
+ MultiOverride();
+
+ return Test.Ret();
+ }
+
+ private static void SingleOverride()
+ {
+ IBarImpl barImpl = new IBarImpl();
+ IFoo foo = (IFoo) barImpl;
+
+ Console.WriteLine("Calling IFoo.Foo methods on IBarImpl...");
+
+ Test.Assert(foo.Foo1(1) == 11, "Calling IFoo.Foo1 on IBarImpl");
+ Test.Assert(foo.Foo2(2) == 22, "Calling IFoo.Foo2 on IBarImpl");
+ Test.Assert(foo.Foo3(3) == 33, "Calling IFoo.Foo3 on IBarImpl");
+ Test.Assert(foo.Foo4(4) == 44, "Calling IFoo.Foo4 on IBarImpl");
+ Test.Assert(foo.Foo5(5) == 55, "Calling IFoo.Foo5 on IBarImpl");
+ Test.Assert(foo.Foo6(0) == 6, "Calling IFoo.Foo6 on IBarImpl");
+ Test.Assert(foo.Foo7(0) == 7, "Calling IFoo.Foo7 on IBarImpl");
+ Test.Assert(foo.Foo8(0) == 8, "Calling IFoo.Foo8 on IBarImpl");
+ Test.Assert(foo.Foo9(0) == 9, "Calling IFoo.Foo9 on IBarImpl");
+
+ IBar bar = (IBar) barImpl;
+
+ Console.WriteLine("Calling IBar.Bar methods on IBarImpl...");
+
+ Test.Assert(bar.Bar1(0) == 11, "Calling IBar.Bar1 on IBarImpl");
+ Test.Assert(bar.Bar2(0) == 22, "Calling IBar.Bar2 on IBarImpl");
+ Test.Assert(bar.Bar3(0) == 33, "Calling IBar.Bar3 on IBarImpl");
+ Test.Assert(bar.Bar4(0) == 44, "Calling IBar.Bar4 on IBarImpl");
+ Test.Assert(bar.Bar5(0) == 55, "Calling IBar.Bar5 on IBarImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on IBarImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on IBarImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on IBarImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on IBarImpl");
+
+ IBlahImpl blahImpl = new IBlahImpl();
+ foo = (IFoo) blahImpl;
+
+ Test.Assert(foo.Foo1(1) == 11, "Calling IFoo.Foo1 on IBlahImpl");
+ Test.Assert(foo.Foo2(2) == 22, "Calling IFoo.Foo2 on IBlahImpl");
+ Test.Assert(foo.Foo3(3) == 33, "Calling IFoo.Foo3 on IBlahImpl");
+ Test.Assert(foo.Foo4(4) == 44, "Calling IFoo.Foo4 on IBlahImpl");
+ Test.Assert(foo.Foo5(5) == 55, "Calling IFoo.Foo5 on IBlahImpl");
+ Test.Assert(foo.Foo6(6) == 66, "Calling IFoo.Foo6 on IBlahImpl");
+ Test.Assert(foo.Foo7(7) == 77, "Calling IFoo.Foo7 on IBlahImpl");
+ Test.Assert(foo.Foo8(8) == 88, "Calling IFoo.Foo8 on IBlahImpl");
+ Test.Assert(foo.Foo9(9) == 99, "Calling IFoo.Foo9 on IBlahImpl");
+
+ bar = (IBar) blahImpl;
+
+ Console.WriteLine("Calling IBar.Bar methods on IBlahImpl...");
+
+ Test.Assert(bar.Bar1(1) == 111, "Calling IBar.Bar1 on IBlahImpl");
+ Test.Assert(bar.Bar2(2) == 222, "Calling IBar.Bar2 on IBlahImpl");
+ Test.Assert(bar.Bar3(3) == 333, "Calling IBar.Bar3 on IBlahImpl");
+ Test.Assert(bar.Bar4(4) == 444, "Calling IBar.Bar4 on IBlahImpl");
+ Test.Assert(bar.Bar5(5) == 555, "Calling IBar.Bar5 on IBlahImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on IBlahImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on IBlahImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on IBlahImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on IBlahImpl");
+
+ IBlah blah = (IBlah) blahImpl;
+
+ Console.WriteLine("Calling IBlah.Blah methods on IBlahImpl...");
+
+ Test.Assert(blah.Blah1(0) == 111, "Calling IBlah.Blah1 on IBlahImpl");
+ Test.Assert(blah.Blah2(2) == 2222, "Calling IBlah.Blah1 on IBlahImpl");
+ Test.Assert(blah.Blah3(3) == 3333, "Calling IBlah.Blah1 on IBlahImpl");
+ }
+
+ private static void MultiOverride()
+ {
+ FooBarBlahImpl fooBarBlah = new FooBarBlahImpl();
+ IFoo foo = (IFoo) fooBarBlah;
+
+ Console.WriteLine("Calling IFoo.Foo methods on FooBarBlahImpl...");
+ Test.Assert(foo.Foo1(0) == 11111, "Calling IFoo.Foo1 on FooBarBlahImpl");
+ Test.Assert(foo.Foo2(0) == 22222, "Calling IFoo.Foo2 on FooBarBlahImpl");
+ Test.Assert(foo.Foo3(0) == 33333, "Calling IFoo.Foo3 on FooBarBlahImpl");
+ Test.Assert(foo.Foo4(0) == 33333, "Calling IFoo.Foo4 on FooBarBlahImpl");
+ Test.Assert(foo.Foo5(0) == 33333, "Calling IFoo.Foo5 on FooBarBlahImpl");
+ Test.Assert(foo.Foo6(6) == 66, "Calling IFoo.Foo6 on FooBarBlahImpl");
+ Test.Assert(foo.Foo7(7) == 77, "Calling IFoo.Foo7 on FooBarBlahImpl");
+ Test.Assert(foo.Foo8(8) == 88, "Calling IFoo.Foo8 on FooBarBlahImpl");
+ Test.Assert(foo.Foo9(9) == 99, "Calling IFoo.Foo9 on FooBarBlahImpl");
+
+ IBar bar = (IBar) fooBarBlah;
+
+ Console.WriteLine("Calling IBar.Bar methods on FooBarBlahImpl...");
+
+ Test.Assert(bar.Bar1(0) == 11111, "Calling IBar.Bar1 on FooBarBlahImpl");
+ Test.Assert(bar.Bar2(0) == 22222, "Calling IBar.Bar2 on FooBarBlahImpl");
+ Test.Assert(bar.Bar3(0) == 33333, "Calling IBar.Bar3 on FooBarBlahImpl");
+ Test.Assert(bar.Bar4(0) == 33333, "Calling IBar.Bar4 on FooBarBlahImpl");
+ Test.Assert(bar.Bar5(0) == 33333, "Calling IBar.Bar5 on FooBarBlahImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on FooBarBlahImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on FooBarBlahImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on FooBarBlahImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on FooBarBlahImpl");
+
+ IBlah blah = (IBlah) fooBarBlah;
+
+ Console.WriteLine("Calling IBlah.Blah methods on FooBarBlahImpl...");
+
+ Test.Assert(blah.Blah1(0) == 11111, "Calling IBlah.Blah1 on FooBarBlahImpl");
+ Test.Assert(blah.Blah2(0) == 22222, "Calling IBlah.Blah1 on FooBarBlahImpl");
+ Test.Assert(blah.Blah3(0) == 33333, "Calling IBlah.Blah1 on FooBarBlahImpl");
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il
new file mode 100644
index 0000000000..7f9444283e
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il
@@ -0,0 +1,1677 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly methodimpl
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module methodimpl.exe
+// MVID: {F249A85F-3FD2-488F-B084-97B542AD68D6}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x02FD0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Foo1(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IIFoo.Foo1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 1
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo1
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo2(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 2
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo2
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo3(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 3
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo3
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo4(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 4
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo4
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo5(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 5
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo5
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo6(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo6"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 6
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo6
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo7(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 7
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo7
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo8(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 8
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo8
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo9(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 9
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo9
+} // end of class IFoo
+
+.class interface private abstract auto ansi IBar
+ implements IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Bar1(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IIBar.Bar1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 11
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar1
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar2(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 22
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar2
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar3(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 33
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar3
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar4(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 44
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar4
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar5(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 55
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar5
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar6(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar6"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 66
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar6
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar7(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 77
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar7
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar8(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 88
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar8
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar9(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 99
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar9
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IFoo
+ //////////////////////////////////////////////////////////////////////////////
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo1(int32 a) cil managed
+ {
+ .override IFoo::Foo1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 10
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo2(int32 a) cil managed
+ {
+ .override IFoo::Foo2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 20
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo2
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo3(int32 a) cil managed
+ {
+ .override IFoo::Foo3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 30
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo3
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo4(int32 a) cil managed
+ {
+ .override IFoo::Foo4
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 40
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo4
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo5(int32 a) cil managed
+ {
+ .override IFoo::Foo5
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 50
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo5
+} // end of class IBar
+
+.class interface private abstract auto ansi IBlah
+ implements IBar,
+ IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Blah1(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 111
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah1
+
+ .method public hidebysig newslot virtual
+ instance int32 Blah2(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 222
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah2
+
+ .method public hidebysig newslot virtual
+ instance int32 Blah3(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 333
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah3
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IFoo
+ //////////////////////////////////////////////////////////////////////////////
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo6(int32 a) cil managed
+ {
+ .override IFoo::Foo6
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo6"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 60
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo6
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo7(int32 a) cil managed
+ {
+ .override IFoo::Foo7
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 70
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo6
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo8(int32 a) cil managed
+ {
+ .override IFoo::Foo8
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 80
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo8
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo9(int32 a) cil managed
+ {
+ .override IFoo::Foo9
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 90
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo9
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IBar
+ //////////////////////////////////////////////////////////////////////////////
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar1(int32 a) cil managed
+ {
+ .override IBar::Bar1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 110
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar2(int32 a) cil managed
+ {
+ .override IBar::Bar2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 220
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar2
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar3(int32 a) cil managed
+ {
+ .override IBar::Bar3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 330
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar3
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar4(int32 a) cil managed
+ {
+ .override IBar::Bar4
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 440
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar4
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar5(int32 a) cil managed
+ {
+ .override IBar::Bar5
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 550
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar5
+} // end of class IBlah
+
+.class private auto ansi beforefieldinit IBarImpl
+ extends [mscorlib]System.Object
+ implements IBar,
+ IFoo
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method IBarImpl::.ctor
+
+} // end of class IBarImpl
+
+.class private auto ansi beforefieldinit IBlahImpl
+ extends IBarImpl
+ implements IBlah,
+ IBar,
+ IFoo
+{
+ .method private hidebysig newslot virtual final
+ instance int32 IBlah.Blah2(int32 c) cil managed
+ {
+ .override IBlah::Blah2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlahImpl::IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 2220
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlahImpl::IBlah.Blah2
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBlah.Blah3(int32 c) cil managed
+ {
+ .override IBlah::Blah3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlahImpl::IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 3330
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlahImpl::IBlah.Blah3
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void IBarImpl::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method IBlahImpl::.ctor
+
+} // end of class IBlahImpl
+
+.class interface private abstract auto ansi IFooBarBlah
+ implements IFoo,
+ IBar,
+ IBlah
+{
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah1(int32 c) cil managed
+ {
+ .override IFoo::Foo1
+ .override IBar::Bar1
+ .override IBlah::Blah1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 11111
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah1
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah2(int32 c) cil managed
+ {
+ .override IFoo::Foo2
+ .override IBar::Bar2
+ .override IBlah::Blah2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 22222
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah3(int32 c) cil managed
+ {
+ .override IFoo::Foo3
+ .override IFoo::Foo4
+ .override IFoo::Foo5
+ .override IBar::Bar3
+ .override IBar::Bar4
+ .override IBar::Bar5
+ .override IBlah::Blah3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 33333
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah3
+} // end of class IFooBarBlah
+
+.class private auto ansi beforefieldinit FooBarBlahImpl
+ implements IFooBarBlah,
+ IFoo,
+ IBar,
+ IBlah
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void IBlahImpl::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooBarBlahImpl::.ctor
+
+} // end of class FooBarBlahImpl
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 23 (0x17)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: call void Program::SingleOverride()
+ IL_0006: nop
+ IL_0007: call void Program::MultiOverride()
+ IL_000c: nop
+ IL_000d: call int32 Test::Ret()
+ IL_0012: stloc.0
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.0
+ IL_0016: ret
+ } // end of method Program::Main
+
+ .method private hidebysig static void SingleOverride() cil managed
+ {
+ // Code size 946 (0x3b2)
+ .maxstack 2
+ .locals init (class IBarImpl V_0,
+ class IFoo V_1,
+ class IBar V_2,
+ class IBlahImpl V_3,
+ class IBlah V_4)
+ IL_0000: nop
+ IL_0001: newobj instance void IBarImpl::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldstr "Calling IFoo.Foo methods on IBarImpl..."
+ IL_000e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0013: nop
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.1
+ IL_0016: callvirt instance int32 IFoo::Foo1(int32)
+ IL_001b: ldc.i4.s 11
+ IL_001d: ceq
+ IL_001f: ldstr "Calling IFoo.Foo1 on IBarImpl"
+ IL_0024: call void Test::Assert(bool,
+ string)
+ IL_0029: nop
+ IL_002a: ldloc.1
+ IL_002b: ldc.i4.2
+ IL_002c: callvirt instance int32 IFoo::Foo2(int32)
+ IL_0031: ldc.i4.s 22
+ IL_0033: ceq
+ IL_0035: ldstr "Calling IFoo.Foo2 on IBarImpl"
+ IL_003a: call void Test::Assert(bool,
+ string)
+ IL_003f: nop
+ IL_0040: ldloc.1
+ IL_0041: ldc.i4.3
+ IL_0042: callvirt instance int32 IFoo::Foo3(int32)
+ IL_0047: ldc.i4.s 33
+ IL_0049: ceq
+ IL_004b: ldstr "Calling IFoo.Foo3 on IBarImpl"
+ IL_0050: call void Test::Assert(bool,
+ string)
+ IL_0055: nop
+ IL_0056: ldloc.1
+ IL_0057: ldc.i4.4
+ IL_0058: callvirt instance int32 IFoo::Foo4(int32)
+ IL_005d: ldc.i4.s 44
+ IL_005f: ceq
+ IL_0061: ldstr "Calling IFoo.Foo4 on IBarImpl"
+ IL_0066: call void Test::Assert(bool,
+ string)
+ IL_006b: nop
+ IL_006c: ldloc.1
+ IL_006d: ldc.i4.5
+ IL_006e: callvirt instance int32 IFoo::Foo5(int32)
+ IL_0073: ldc.i4.s 55
+ IL_0075: ceq
+ IL_0077: ldstr "Calling IFoo.Foo5 on IBarImpl"
+ IL_007c: call void Test::Assert(bool,
+ string)
+ IL_0081: nop
+ IL_0082: ldloc.1
+ IL_0083: ldc.i4.0
+ IL_0084: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0089: ldc.i4.6
+ IL_008a: ceq
+ IL_008c: ldstr "Calling IFoo.Foo6 on IBarImpl"
+ IL_0091: call void Test::Assert(bool,
+ string)
+ IL_0096: nop
+ IL_0097: ldloc.1
+ IL_0098: ldc.i4.0
+ IL_0099: callvirt instance int32 IFoo::Foo7(int32)
+ IL_009e: ldc.i4.7
+ IL_009f: ceq
+ IL_00a1: ldstr "Calling IFoo.Foo7 on IBarImpl"
+ IL_00a6: call void Test::Assert(bool,
+ string)
+ IL_00ab: nop
+ IL_00ac: ldloc.1
+ IL_00ad: ldc.i4.0
+ IL_00ae: callvirt instance int32 IFoo::Foo8(int32)
+ IL_00b3: ldc.i4.8
+ IL_00b4: ceq
+ IL_00b6: ldstr "Calling IFoo.Foo8 on IBarImpl"
+ IL_00bb: call void Test::Assert(bool,
+ string)
+ IL_00c0: nop
+ IL_00c1: ldloc.1
+ IL_00c2: ldc.i4.0
+ IL_00c3: callvirt instance int32 IFoo::Foo9(int32)
+ IL_00c8: ldc.i4.s 9
+ IL_00ca: ceq
+ IL_00cc: ldstr "Calling IFoo.Foo9 on IBarImpl"
+ IL_00d1: call void Test::Assert(bool,
+ string)
+ IL_00d6: nop
+ IL_00d7: ldloc.0
+ IL_00d8: stloc.2
+ IL_00d9: ldstr "Calling IBar.Bar methods on IBarImpl..."
+ IL_00de: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00e3: nop
+ IL_00e4: ldloc.2
+ IL_00e5: ldc.i4.0
+ IL_00e6: callvirt instance int32 IBar::Bar1(int32)
+ IL_00eb: ldc.i4.s 11
+ IL_00ed: ceq
+ IL_00ef: ldstr "Calling IBar.Bar1 on IBarImpl"
+ IL_00f4: call void Test::Assert(bool,
+ string)
+ IL_00f9: nop
+ IL_00fa: ldloc.2
+ IL_00fb: ldc.i4.0
+ IL_00fc: callvirt instance int32 IBar::Bar2(int32)
+ IL_0101: ldc.i4.s 22
+ IL_0103: ceq
+ IL_0105: ldstr "Calling IBar.Bar2 on IBarImpl"
+ IL_010a: call void Test::Assert(bool,
+ string)
+ IL_010f: nop
+ IL_0110: ldloc.2
+ IL_0111: ldc.i4.0
+ IL_0112: callvirt instance int32 IBar::Bar3(int32)
+ IL_0117: ldc.i4.s 33
+ IL_0119: ceq
+ IL_011b: ldstr "Calling IBar.Bar3 on IBarImpl"
+ IL_0120: call void Test::Assert(bool,
+ string)
+ IL_0125: nop
+ IL_0126: ldloc.2
+ IL_0127: ldc.i4.0
+ IL_0128: callvirt instance int32 IBar::Bar4(int32)
+ IL_012d: ldc.i4.s 44
+ IL_012f: ceq
+ IL_0131: ldstr "Calling IBar.Bar4 on IBarImpl"
+ IL_0136: call void Test::Assert(bool,
+ string)
+ IL_013b: nop
+ IL_013c: ldloc.2
+ IL_013d: ldc.i4.0
+ IL_013e: callvirt instance int32 IBar::Bar5(int32)
+ IL_0143: ldc.i4.s 55
+ IL_0145: ceq
+ IL_0147: ldstr "Calling IBar.Bar5 on IBarImpl"
+ IL_014c: call void Test::Assert(bool,
+ string)
+ IL_0151: nop
+ IL_0152: ldloc.2
+ IL_0153: ldc.i4.0
+ IL_0154: callvirt instance int32 IBar::Bar6(int32)
+ IL_0159: ldc.i4.s 66
+ IL_015b: ceq
+ IL_015d: ldstr "Calling IBar.Bar6 on IBarImpl"
+ IL_0162: call void Test::Assert(bool,
+ string)
+ IL_0167: nop
+ IL_0168: ldloc.2
+ IL_0169: ldc.i4.0
+ IL_016a: callvirt instance int32 IBar::Bar7(int32)
+ IL_016f: ldc.i4.s 77
+ IL_0171: ceq
+ IL_0173: ldstr "Calling IBar.Bar7 on IBarImpl"
+ IL_0178: call void Test::Assert(bool,
+ string)
+ IL_017d: nop
+ IL_017e: ldloc.2
+ IL_017f: ldc.i4.0
+ IL_0180: callvirt instance int32 IBar::Bar8(int32)
+ IL_0185: ldc.i4.s 88
+ IL_0187: ceq
+ IL_0189: ldstr "Calling IBar.Bar8 on IBarImpl"
+ IL_018e: call void Test::Assert(bool,
+ string)
+ IL_0193: nop
+ IL_0194: ldloc.2
+ IL_0195: ldc.i4.0
+ IL_0196: callvirt instance int32 IBar::Bar9(int32)
+ IL_019b: ldc.i4.s 99
+ IL_019d: ceq
+ IL_019f: ldstr "Calling IBar.Bar9 on IBarImpl"
+ IL_01a4: call void Test::Assert(bool,
+ string)
+ IL_01a9: nop
+ IL_01aa: newobj instance void IBlahImpl::.ctor()
+ IL_01af: stloc.3
+ IL_01b0: ldloc.3
+ IL_01b1: stloc.1
+ IL_01b2: ldloc.1
+ IL_01b3: ldc.i4.1
+ IL_01b4: callvirt instance int32 IFoo::Foo1(int32)
+ IL_01b9: ldc.i4.s 11
+ IL_01bb: ceq
+ IL_01bd: ldstr "Calling IFoo.Foo1 on IBlahImpl"
+ IL_01c2: call void Test::Assert(bool,
+ string)
+ IL_01c7: nop
+ IL_01c8: ldloc.1
+ IL_01c9: ldc.i4.2
+ IL_01ca: callvirt instance int32 IFoo::Foo2(int32)
+ IL_01cf: ldc.i4.s 22
+ IL_01d1: ceq
+ IL_01d3: ldstr "Calling IFoo.Foo2 on IBlahImpl"
+ IL_01d8: call void Test::Assert(bool,
+ string)
+ IL_01dd: nop
+ IL_01de: ldloc.1
+ IL_01df: ldc.i4.3
+ IL_01e0: callvirt instance int32 IFoo::Foo3(int32)
+ IL_01e5: ldc.i4.s 33
+ IL_01e7: ceq
+ IL_01e9: ldstr "Calling IFoo.Foo3 on IBlahImpl"
+ IL_01ee: call void Test::Assert(bool,
+ string)
+ IL_01f3: nop
+ IL_01f4: ldloc.1
+ IL_01f5: ldc.i4.4
+ IL_01f6: callvirt instance int32 IFoo::Foo4(int32)
+ IL_01fb: ldc.i4.s 44
+ IL_01fd: ceq
+ IL_01ff: ldstr "Calling IFoo.Foo4 on IBlahImpl"
+ IL_0204: call void Test::Assert(bool,
+ string)
+ IL_0209: nop
+ IL_020a: ldloc.1
+ IL_020b: ldc.i4.5
+ IL_020c: callvirt instance int32 IFoo::Foo5(int32)
+ IL_0211: ldc.i4.s 55
+ IL_0213: ceq
+ IL_0215: ldstr "Calling IFoo.Foo5 on IBlahImpl"
+ IL_021a: call void Test::Assert(bool,
+ string)
+ IL_021f: nop
+ IL_0220: ldloc.1
+ IL_0221: ldc.i4.6
+ IL_0222: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0227: ldc.i4.s 66
+ IL_0229: ceq
+ IL_022b: ldstr "Calling IFoo.Foo6 on IBlahImpl"
+ IL_0230: call void Test::Assert(bool,
+ string)
+ IL_0235: nop
+ IL_0236: ldloc.1
+ IL_0237: ldc.i4.7
+ IL_0238: callvirt instance int32 IFoo::Foo7(int32)
+ IL_023d: ldc.i4.s 77
+ IL_023f: ceq
+ IL_0241: ldstr "Calling IFoo.Foo7 on IBlahImpl"
+ IL_0246: call void Test::Assert(bool,
+ string)
+ IL_024b: nop
+ IL_024c: ldloc.1
+ IL_024d: ldc.i4.8
+ IL_024e: callvirt instance int32 IFoo::Foo8(int32)
+ IL_0253: ldc.i4.s 88
+ IL_0255: ceq
+ IL_0257: ldstr "Calling IFoo.Foo8 on IBlahImpl"
+ IL_025c: call void Test::Assert(bool,
+ string)
+ IL_0261: nop
+ IL_0262: ldloc.1
+ IL_0263: ldc.i4.s 9
+ IL_0265: callvirt instance int32 IFoo::Foo9(int32)
+ IL_026a: ldc.i4.s 99
+ IL_026c: ceq
+ IL_026e: ldstr "Calling IFoo.Foo9 on IBlahImpl"
+ IL_0273: call void Test::Assert(bool,
+ string)
+ IL_0278: nop
+ IL_0279: ldloc.3
+ IL_027a: stloc.2
+ IL_027b: ldstr "Calling IBar.Bar methods on IBlahImpl..."
+ IL_0280: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0285: nop
+ IL_0286: ldloc.2
+ IL_0287: ldc.i4.1
+ IL_0288: callvirt instance int32 IBar::Bar1(int32)
+ IL_028d: ldc.i4.s 111
+ IL_028f: ceq
+ IL_0291: ldstr "Calling IBar.Bar1 on IBlahImpl"
+ IL_0296: call void Test::Assert(bool,
+ string)
+ IL_029b: nop
+ IL_029c: ldloc.2
+ IL_029d: ldc.i4.2
+ IL_029e: callvirt instance int32 IBar::Bar2(int32)
+ IL_02a3: ldc.i4 0xde
+ IL_02a8: ceq
+ IL_02aa: ldstr "Calling IBar.Bar2 on IBlahImpl"
+ IL_02af: call void Test::Assert(bool,
+ string)
+ IL_02b4: nop
+ IL_02b5: ldloc.2
+ IL_02b6: ldc.i4.3
+ IL_02b7: callvirt instance int32 IBar::Bar3(int32)
+ IL_02bc: ldc.i4 0x14d
+ IL_02c1: ceq
+ IL_02c3: ldstr "Calling IBar.Bar3 on IBlahImpl"
+ IL_02c8: call void Test::Assert(bool,
+ string)
+ IL_02cd: nop
+ IL_02ce: ldloc.2
+ IL_02cf: ldc.i4.4
+ IL_02d0: callvirt instance int32 IBar::Bar4(int32)
+ IL_02d5: ldc.i4 0x1bc
+ IL_02da: ceq
+ IL_02dc: ldstr "Calling IBar.Bar4 on IBlahImpl"
+ IL_02e1: call void Test::Assert(bool,
+ string)
+ IL_02e6: nop
+ IL_02e7: ldloc.2
+ IL_02e8: ldc.i4.5
+ IL_02e9: callvirt instance int32 IBar::Bar5(int32)
+ IL_02ee: ldc.i4 0x22b
+ IL_02f3: ceq
+ IL_02f5: ldstr "Calling IBar.Bar5 on IBlahImpl"
+ IL_02fa: call void Test::Assert(bool,
+ string)
+ IL_02ff: nop
+ IL_0300: ldloc.2
+ IL_0301: ldc.i4.0
+ IL_0302: callvirt instance int32 IBar::Bar6(int32)
+ IL_0307: ldc.i4.s 66
+ IL_0309: ceq
+ IL_030b: ldstr "Calling IBar.Bar6 on IBlahImpl"
+ IL_0310: call void Test::Assert(bool,
+ string)
+ IL_0315: nop
+ IL_0316: ldloc.2
+ IL_0317: ldc.i4.0
+ IL_0318: callvirt instance int32 IBar::Bar7(int32)
+ IL_031d: ldc.i4.s 77
+ IL_031f: ceq
+ IL_0321: ldstr "Calling IBar.Bar7 on IBlahImpl"
+ IL_0326: call void Test::Assert(bool,
+ string)
+ IL_032b: nop
+ IL_032c: ldloc.2
+ IL_032d: ldc.i4.0
+ IL_032e: callvirt instance int32 IBar::Bar8(int32)
+ IL_0333: ldc.i4.s 88
+ IL_0335: ceq
+ IL_0337: ldstr "Calling IBar.Bar8 on IBlahImpl"
+ IL_033c: call void Test::Assert(bool,
+ string)
+ IL_0341: nop
+ IL_0342: ldloc.2
+ IL_0343: ldc.i4.0
+ IL_0344: callvirt instance int32 IBar::Bar9(int32)
+ IL_0349: ldc.i4.s 99
+ IL_034b: ceq
+ IL_034d: ldstr "Calling IBar.Bar9 on IBlahImpl"
+ IL_0352: call void Test::Assert(bool,
+ string)
+ IL_0357: nop
+ IL_0358: ldloc.3
+ IL_0359: stloc.s V_4
+ IL_035b: ldstr "Calling IBlah.Blah methods on IBlahImpl..."
+ IL_0360: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0365: nop
+ IL_0366: ldloc.s V_4
+ IL_0368: ldc.i4.0
+ IL_0369: callvirt instance int32 IBlah::Blah1(int32)
+ IL_036e: ldc.i4.s 111
+ IL_0370: ceq
+ IL_0372: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_0377: call void Test::Assert(bool,
+ string)
+ IL_037c: nop
+ IL_037d: ldloc.s V_4
+ IL_037f: ldc.i4.2
+ IL_0380: callvirt instance int32 IBlah::Blah2(int32)
+ IL_0385: ldc.i4 0x8ae
+ IL_038a: ceq
+ IL_038c: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_0391: call void Test::Assert(bool,
+ string)
+ IL_0396: nop
+ IL_0397: ldloc.s V_4
+ IL_0399: ldc.i4.3
+ IL_039a: callvirt instance int32 IBlah::Blah3(int32)
+ IL_039f: ldc.i4 0xd05
+ IL_03a4: ceq
+ IL_03a6: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_03ab: call void Test::Assert(bool,
+ string)
+ IL_03b0: nop
+ IL_03b1: ret
+ } // end of method Program::SingleOverride
+
+ .method private hidebysig static void MultiOverride() cil managed
+ {
+ // Code size 549 (0x225)
+ .maxstack 2
+ .locals init (class FooBarBlahImpl V_0,
+ class IFoo V_1,
+ class IBar V_2,
+ class IBlah V_3)
+ IL_0000: nop
+ IL_0001: newobj instance void FooBarBlahImpl::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldstr "Calling IFoo.Foo methods on FooBarBlahImpl..."
+ IL_000e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0013: nop
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.0
+ IL_0016: callvirt instance int32 IFoo::Foo1(int32)
+ IL_001b: ldc.i4 0x2b67
+ IL_0020: ceq
+ IL_0022: ldstr "Calling IFoo.Foo1 on FooBarBlahImpl"
+ IL_0027: call void Test::Assert(bool,
+ string)
+ IL_002c: nop
+ IL_002d: ldloc.1
+ IL_002e: ldc.i4.0
+ IL_002f: callvirt instance int32 IFoo::Foo2(int32)
+ IL_0034: ldc.i4 0x56ce
+ IL_0039: ceq
+ IL_003b: ldstr "Calling IFoo.Foo2 on FooBarBlahImpl"
+ IL_0040: call void Test::Assert(bool,
+ string)
+ IL_0045: nop
+ IL_0046: ldloc.1
+ IL_0047: ldc.i4.0
+ IL_0048: callvirt instance int32 IFoo::Foo3(int32)
+ IL_004d: ldc.i4 0x8235
+ IL_0052: ceq
+ IL_0054: ldstr "Calling IFoo.Foo3 on FooBarBlahImpl"
+ IL_0059: call void Test::Assert(bool,
+ string)
+ IL_005e: nop
+ IL_005f: ldloc.1
+ IL_0060: ldc.i4.0
+ IL_0061: callvirt instance int32 IFoo::Foo4(int32)
+ IL_0066: ldc.i4 0x8235
+ IL_006b: ceq
+ IL_006d: ldstr "Calling IFoo.Foo4 on FooBarBlahImpl"
+ IL_0072: call void Test::Assert(bool,
+ string)
+ IL_0077: nop
+ IL_0078: ldloc.1
+ IL_0079: ldc.i4.0
+ IL_007a: callvirt instance int32 IFoo::Foo5(int32)
+ IL_007f: ldc.i4 0x8235
+ IL_0084: ceq
+ IL_0086: ldstr "Calling IFoo.Foo5 on FooBarBlahImpl"
+ IL_008b: call void Test::Assert(bool,
+ string)
+ IL_0090: nop
+ IL_0091: ldloc.1
+ IL_0092: ldc.i4.6
+ IL_0093: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0098: ldc.i4.s 66
+ IL_009a: ceq
+ IL_009c: ldstr "Calling IFoo.Foo6 on FooBarBlahImpl"
+ IL_00a1: call void Test::Assert(bool,
+ string)
+ IL_00a6: nop
+ IL_00a7: ldloc.1
+ IL_00a8: ldc.i4.7
+ IL_00a9: callvirt instance int32 IFoo::Foo7(int32)
+ IL_00ae: ldc.i4.s 77
+ IL_00b0: ceq
+ IL_00b2: ldstr "Calling IFoo.Foo7 on FooBarBlahImpl"
+ IL_00b7: call void Test::Assert(bool,
+ string)
+ IL_00bc: nop
+ IL_00bd: ldloc.1
+ IL_00be: ldc.i4.8
+ IL_00bf: callvirt instance int32 IFoo::Foo8(int32)
+ IL_00c4: ldc.i4.s 88
+ IL_00c6: ceq
+ IL_00c8: ldstr "Calling IFoo.Foo8 on FooBarBlahImpl"
+ IL_00cd: call void Test::Assert(bool,
+ string)
+ IL_00d2: nop
+ IL_00d3: ldloc.1
+ IL_00d4: ldc.i4.s 9
+ IL_00d6: callvirt instance int32 IFoo::Foo9(int32)
+ IL_00db: ldc.i4.s 99
+ IL_00dd: ceq
+ IL_00df: ldstr "Calling IFoo.Foo9 on FooBarBlahImpl"
+ IL_00e4: call void Test::Assert(bool,
+ string)
+ IL_00e9: nop
+ IL_00ea: ldloc.0
+ IL_00eb: stloc.2
+ IL_00ec: ldstr "Calling IBar.Bar methods on FooBarBlahImpl..."
+ IL_00f1: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00f6: nop
+ IL_00f7: ldloc.2
+ IL_00f8: ldc.i4.0
+ IL_00f9: callvirt instance int32 IBar::Bar1(int32)
+ IL_00fe: ldc.i4 0x2b67
+ IL_0103: ceq
+ IL_0105: ldstr "Calling IBar.Bar1 on FooBarBlahImpl"
+ IL_010a: call void Test::Assert(bool,
+ string)
+ IL_010f: nop
+ IL_0110: ldloc.2
+ IL_0111: ldc.i4.0
+ IL_0112: callvirt instance int32 IBar::Bar2(int32)
+ IL_0117: ldc.i4 0x56ce
+ IL_011c: ceq
+ IL_011e: ldstr "Calling IBar.Bar2 on FooBarBlahImpl"
+ IL_0123: call void Test::Assert(bool,
+ string)
+ IL_0128: nop
+ IL_0129: ldloc.2
+ IL_012a: ldc.i4.0
+ IL_012b: callvirt instance int32 IBar::Bar3(int32)
+ IL_0130: ldc.i4 0x8235
+ IL_0135: ceq
+ IL_0137: ldstr "Calling IBar.Bar3 on FooBarBlahImpl"
+ IL_013c: call void Test::Assert(bool,
+ string)
+ IL_0141: nop
+ IL_0142: ldloc.2
+ IL_0143: ldc.i4.0
+ IL_0144: callvirt instance int32 IBar::Bar4(int32)
+ IL_0149: ldc.i4 0x8235
+ IL_014e: ceq
+ IL_0150: ldstr "Calling IBar.Bar4 on FooBarBlahImpl"
+ IL_0155: call void Test::Assert(bool,
+ string)
+ IL_015a: nop
+ IL_015b: ldloc.2
+ IL_015c: ldc.i4.0
+ IL_015d: callvirt instance int32 IBar::Bar5(int32)
+ IL_0162: ldc.i4 0x8235
+ IL_0167: ceq
+ IL_0169: ldstr "Calling IBar.Bar5 on FooBarBlahImpl"
+ IL_016e: call void Test::Assert(bool,
+ string)
+ IL_0173: nop
+ IL_0174: ldloc.2
+ IL_0175: ldc.i4.0
+ IL_0176: callvirt instance int32 IBar::Bar6(int32)
+ IL_017b: ldc.i4.s 66
+ IL_017d: ceq
+ IL_017f: ldstr "Calling IBar.Bar6 on FooBarBlahImpl"
+ IL_0184: call void Test::Assert(bool,
+ string)
+ IL_0189: nop
+ IL_018a: ldloc.2
+ IL_018b: ldc.i4.0
+ IL_018c: callvirt instance int32 IBar::Bar7(int32)
+ IL_0191: ldc.i4.s 77
+ IL_0193: ceq
+ IL_0195: ldstr "Calling IBar.Bar7 on FooBarBlahImpl"
+ IL_019a: call void Test::Assert(bool,
+ string)
+ IL_019f: nop
+ IL_01a0: ldloc.2
+ IL_01a1: ldc.i4.0
+ IL_01a2: callvirt instance int32 IBar::Bar8(int32)
+ IL_01a7: ldc.i4.s 88
+ IL_01a9: ceq
+ IL_01ab: ldstr "Calling IBar.Bar8 on FooBarBlahImpl"
+ IL_01b0: call void Test::Assert(bool,
+ string)
+ IL_01b5: nop
+ IL_01b6: ldloc.2
+ IL_01b7: ldc.i4.0
+ IL_01b8: callvirt instance int32 IBar::Bar9(int32)
+ IL_01bd: ldc.i4.s 99
+ IL_01bf: ceq
+ IL_01c1: ldstr "Calling IBar.Bar9 on FooBarBlahImpl"
+ IL_01c6: call void Test::Assert(bool,
+ string)
+ IL_01cb: nop
+ IL_01cc: ldloc.0
+ IL_01cd: stloc.3
+ IL_01ce: ldstr "Calling IBlah.Blah methods on FooBarBlahImpl..."
+ IL_01d3: call void [mscorlib]System.Console::WriteLine(string)
+ IL_01d8: nop
+ IL_01d9: ldloc.3
+ IL_01da: ldc.i4.0
+ IL_01db: callvirt instance int32 IBlah::Blah1(int32)
+ IL_01e0: ldc.i4 0x2b67
+ IL_01e5: ceq
+ IL_01e7: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_01ec: call void Test::Assert(bool,
+ string)
+ IL_01f1: nop
+ IL_01f2: ldloc.3
+ IL_01f3: ldc.i4.0
+ IL_01f4: callvirt instance int32 IBlah::Blah2(int32)
+ IL_01f9: ldc.i4 0x56ce
+ IL_01fe: ceq
+ IL_0200: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_0205: call void Test::Assert(bool,
+ string)
+ IL_020a: nop
+ IL_020b: ldloc.3
+ IL_020c: ldc.i4.0
+ IL_020d: callvirt instance int32 IBlah::Blah3(int32)
+ IL_0212: ldc.i4 0x8235
+ IL_0217: ceq
+ IL_0219: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_021e: call void Test::Assert(bool,
+ string)
+ IL_0223: nop
+ IL_0224: ret
+ } // end of method Program::MultiOverride
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file methodimpl.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj
new file mode 100644
index 0000000000..16a1cadcd2
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>methodimpl</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="methodimpl.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs
new file mode 100644
index 0000000000..93b214dfb7
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs
@@ -0,0 +1,68 @@
+using System;
+
+interface IFoo<T>
+{
+ Type Foo(T a);
+}
+
+interface IBar<in T>
+{
+ Type Bar(T b);
+}
+
+class FooBar<T, U> : IFoo<T>, IBar<U>
+{
+ public Type Foo(T a)
+ {
+ Console.WriteLine("At IFoo.Foo:Arg={0}, TypeOf(T)={1}", a.ToString(), typeof(T));
+ return typeof(T);
+ }
+
+ public Type Bar(U b)
+ {
+ Console.WriteLine("At IBar.Bar:Arg={0}, TypeOf(T)={1}", b.ToString(), typeof(U));
+ return typeof(U);
+ }
+}
+
+class Program
+{
+ public static int Main()
+ {
+ FooBar<string, object> fooBar = new FooBar<string, object>();
+ IFoo<string> foo = (IFoo<string>) fooBar;
+ IBar<string[]> bar = (IBar<string[]>) fooBar;
+
+ Console.WriteLine("Calling IFoo<string>.Foo on FooBar<string, object> - expecting default method IFoo<string>.Foo");
+ Test.Assert(foo.Foo("ABC") == typeof(string), "Calling IFoo<string>.Foo on FooBar<string, object>");
+
+ Console.WriteLine("Calling IBar<string[]>.Foo on FooBar<string, object> - expecting default method IBar<object>.Foo");
+ Test.Assert(bar.Bar(new string[] { "ABC" }) == typeof(object), "Calling IBar<object>.Bar on FooBar<string, object>");
+
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il
new file mode 100644
index 0000000000..8e9eaec325
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il
@@ -0,0 +1,275 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly sharedgenerics
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module sharedgenerics.exe
+// MVID: {0DEEC74C-30FE-495C-9653-12BE5220327A}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x02D40000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IFoo`1<T>
+{
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.Type
+ Foo(!T a) cil managed
+ {
+ // Code size 50 (0x32)
+ .maxstack 3
+ .locals init (class [mscorlib]System.Type V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo:Arg={0}, TypeOf(T)={1}"
+ IL_0006: ldarga.s a
+ IL_0008: constrained. !T
+ IL_000e: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_0013: ldtoken !T
+ IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_001d: call void [mscorlib]System.Console::WriteLine(string,
+ object,
+ object)
+ IL_0022: nop
+ IL_0023: ldtoken !T
+ IL_0028: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_002d: stloc.0
+ IL_002e: br.s IL_0030
+
+ IL_0030: ldloc.0
+ IL_0031: ret
+ } // end of method IFoo`1::Foo
+
+} // end of class IFoo`1
+
+.class interface private abstract auto ansi IBar`1<- T>
+{
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.Type
+ Bar(!T b) cil managed
+ {
+ // Code size 50 (0x32)
+ .maxstack 3
+ .locals init (class [mscorlib]System.Type V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar:Arg={0}, TypeOf(T)={1}"
+ IL_0006: ldarga.s b
+ IL_0008: constrained. !T
+ IL_000e: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_0013: ldtoken !T
+ IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_001d: call void [mscorlib]System.Console::WriteLine(string,
+ object,
+ object)
+ IL_0022: nop
+ IL_0023: ldtoken !T
+ IL_0028: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_002d: stloc.0
+ IL_002e: br.s IL_0030
+
+ IL_0030: ldloc.0
+ IL_0031: ret
+ } // end of method IBar`1::Bar
+
+} // end of class IBar`1
+
+.class private auto ansi beforefieldinit FooBar`2<T,U>
+ extends [mscorlib]System.Object
+ implements class IFoo`1<!T>,
+ class IBar`1<!U>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooBar`2::.ctor
+
+} // end of class FooBar`2
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 126 (0x7e)
+ .maxstack 5
+ .locals init (class FooBar`2<string,object> V_0,
+ class IFoo`1<string> V_1,
+ class IBar`1<string[]> V_2,
+ int32 V_3)
+ IL_0000: nop
+ IL_0001: newobj instance void class FooBar`2<string,object>::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldloc.0
+ IL_000a: stloc.2
+ IL_000b: ldstr "Calling IFoo<string>.Foo on FooBar<string, object>"
+ + " - expecting default method IFoo<string>.Foo"
+ IL_0010: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0015: nop
+ IL_0016: ldloc.1
+ IL_0017: ldstr "ABC"
+ IL_001c: callvirt instance class [mscorlib]System.Type class IFoo`1<string>::Foo(!0)
+ IL_0021: ldtoken [mscorlib]System.String
+ IL_0026: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_002b: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0030: ldstr "Calling IFoo<string>.Foo on FooBar<string, object>"
+ IL_0035: call void Test::Assert(bool,
+ string)
+ IL_003a: nop
+ IL_003b: ldstr "Calling IBar<string[]>.Foo on FooBar<string, objec"
+ + "t> - expecting default method IBar<object>.Foo"
+ IL_0040: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0045: nop
+ IL_0046: ldloc.2
+ IL_0047: ldc.i4.1
+ IL_0048: newarr [mscorlib]System.String
+ IL_004d: dup
+ IL_004e: ldc.i4.0
+ IL_004f: ldstr "ABC"
+ IL_0054: stelem.ref
+ IL_0055: callvirt instance class [mscorlib]System.Type class IBar`1<string[]>::Bar(!0)
+ IL_005a: ldtoken [mscorlib]System.Object
+ IL_005f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0064: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0069: ldstr "Calling IBar<object>.Bar on FooBar<string, object>"
+ IL_006e: call void Test::Assert(bool,
+ string)
+ IL_0073: nop
+ IL_0074: call int32 Test::Ret()
+ IL_0079: stloc.3
+ IL_007a: br.s IL_007c
+
+ IL_007c: ldloc.3
+ IL_007d: ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file sharedgenerics.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj
new file mode 100644
index 0000000000..be40d201ff
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>sharedgenerics</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="sharedgenerics.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs
new file mode 100644
index 0000000000..21e5c8aaf3
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs
@@ -0,0 +1,123 @@
+using System;
+
+interface IBlah
+{
+ int Blah(int c);
+}
+
+// All methods go into IBlah
+class IBlah_Impl
+{
+ public int Blah(int c)
+ {
+ Console.WriteLine("At IBlah.Blah");
+ return c + Blah_Private_GetA() + Blah_Internal_GetB() + Blah_Protected_GetC();
+ }
+
+ private int Blah_Private_GetA()
+ {
+ Console.WriteLine("At IBlah.Blah_Private_GetA");
+ return 1;
+ }
+
+ internal int Blah_Internal_GetB()
+ {
+ Console.WriteLine("At IBlah.Blah_Internal_GetB");
+ return 2;
+ }
+
+ protected int Blah_Protected_GetC()
+ {
+ Console.WriteLine("At IBlah.Blah_Protected_GetC");
+ return 3;
+ }
+}
+
+interface IFoo
+{
+ int Foo(int a);
+}
+
+interface IBar
+{
+ int Bar(int b);
+}
+
+class Base : IBlah
+{
+ public int Blah(int c)
+ {
+ // Dummy
+ return 0;
+ }
+}
+
+class FooBar : Base, IFoo, IBar
+{
+ public int Foo(int a)
+ {
+ Console.WriteLine("At IFoo.Foo");
+ return a+1;
+ }
+
+ public int Bar(int b)
+ {
+ Console.WriteLine("At IBar.Bar");
+ return b+10;
+ }
+
+ public int CallBlahProtected()
+ {
+ // change to IBlah.Blah_Protected_GetC();
+ return CallBlahProtected();
+ }
+}
+
+class Program
+{
+ public static int Main()
+ {
+ FooBar fooBar = new FooBar();
+ IFoo foo = (IFoo) fooBar;
+ IBar bar = (IBar) fooBar;
+ IBlah blah = (IBlah) fooBar;
+
+ Console.WriteLine("Calling IFoo.Foo on FooBar - expecting default method on IFoo.Foo. ");
+ Test.Assert(foo.Foo(10) == 11, "Calling IFoo.Foo on FooBar");
+
+ Console.WriteLine("Calling IBar.Bar on FooBar - expecting default method on IBar.Bar. ");
+ Test.Assert(bar.Bar(10) == 20, "Calling IBar.Bar on FooBar");
+
+ Console.WriteLine("Calling IBlah.Blah on FooBar - expecting default method on IBlah.Blah from Base. ");
+ Test.Assert(blah.Blah(10) == 16, "Calling IBlah.Blah on FooBar");
+
+ Console.WriteLine("Calling FooBar.CallBlahProtected - expecting protected methods on interface can be called");
+ Test.Assert(fooBar.CallBlahProtected() == 3, "Calling FooBar.CallBlahProtected");
+
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il
new file mode 100644
index 0000000000..c53ed0f0a4
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il
@@ -0,0 +1,397 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly simple
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module simple.exe
+// MVID: {0B8FCFD0-673A-4DEB-90CC-B96749DE09C8}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01A80000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IBlah
+{
+ .method public hidebysig newslot virtual
+ instance int32 Blah(int32 c) cil managed
+ {
+ // Code size 39 (0x27)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldarg.0
+ IL_000e: call instance int32 IBlah::Blah_Private_GetA()
+ IL_0013: add
+ IL_0014: ldarg.0
+ IL_0015: call instance int32 IBlah::Blah_Internal_GetB()
+ IL_001a: add
+ IL_001b: ldarg.0
+ IL_001c: call instance int32 IBlah::Blah_Protected_GetC()
+ IL_0021: add
+ IL_0022: stloc.0
+ IL_0023: br.s IL_0025
+
+ IL_0025: ldloc.0
+ IL_0026: ret
+ } // end of method IBlah::Blah
+
+ .method private hidebysig instance int32
+ Blah_Private_GetA() cil managed
+ {
+ // Code size 18 (0x12)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah_Private_GetA"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldc.i4.1
+ IL_000d: stloc.0
+ IL_000e: br.s IL_0010
+
+ IL_0010: ldloc.0
+ IL_0011: ret
+ } // end of method IBlah_Impl::Blah_Private_GetA
+
+ .method assembly hidebysig instance int32
+ Blah_Internal_GetB() cil managed
+ {
+ // Code size 18 (0x12)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah_Internal_GetB"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldc.i4.2
+ IL_000d: stloc.0
+ IL_000e: br.s IL_0010
+
+ IL_0010: ldloc.0
+ IL_0011: ret
+ } // end of method IBlah_Impl::Blah_Internal_GetB
+
+ .method family hidebysig instance int32
+ Blah_Protected_GetC() cil managed
+ {
+ // Code size 18 (0x12)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah_Protected_GetC"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldc.i4.3
+ IL_000d: stloc.0
+ IL_000e: br.s IL_0010
+
+ IL_0010: ldloc.0
+ IL_0011: ret
+ } // end of method IBlah_Impl::Blah_Protected_GetC
+} // end of class IBlah
+
+.class interface private abstract auto ansi IFoo
+{
+ .method public hidebysig newslot virtual
+ instance int32 Foo(int32 a) cil managed
+ {
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.1
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method IFoo::Foo
+
+} // end of class IFoo
+
+.class interface private abstract auto ansi IBar
+{
+ .method public hidebysig newslot virtual
+ instance int32 Bar(int32 b) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 10
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar
+
+} // end of class IBar
+
+.class private auto ansi beforefieldinit Base
+ extends [mscorlib]System.Object
+ implements IBlah
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Base::.ctor
+
+} // end of class Base
+
+.class private auto ansi beforefieldinit FooBar
+ extends Base
+ implements IFoo,
+ IBar
+{
+ .method public hidebysig instance int32
+ CallBlahProtected() cil managed
+ {
+ // Code size 12 (0xc)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: call instance int32 IBlah::Blah_Protected_GetC()
+ IL_0007: stloc.0
+ IL_0008: br.s IL_000a
+
+ IL_000a: ldloc.0
+ IL_000b: ret
+ } // end of method FooBar::CallBlahProtected
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void Base::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooBar::.ctor
+
+} // end of class FooBar
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 158 (0x9e)
+ .maxstack 2
+ .locals init (class FooBar V_0,
+ class IFoo V_1,
+ class IBar V_2,
+ class IBlah V_3,
+ int32 V_4)
+ IL_0000: nop
+ IL_0001: newobj instance void FooBar::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldloc.0
+ IL_000a: stloc.2
+ IL_000b: ldloc.0
+ IL_000c: stloc.3
+ IL_000d: ldstr "Calling IFoo.Foo on FooBar - expecting default met"
+ + "hod on IFoo.Foo. "
+ IL_0012: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0017: nop
+ IL_0018: ldloc.1
+ IL_0019: ldc.i4.s 10
+ IL_001b: callvirt instance int32 IFoo::Foo(int32)
+ IL_0020: ldc.i4.s 11
+ IL_0022: ceq
+ IL_0024: ldstr "Calling IFoo.Foo on FooBar"
+ IL_0029: call void Test::Assert(bool,
+ string)
+ IL_002e: nop
+ IL_002f: ldstr "Calling IBar.Bar on FooBar - expecting default met"
+ + "hod on IBar.Bar. "
+ IL_0034: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0039: nop
+ IL_003a: ldloc.2
+ IL_003b: ldc.i4.s 10
+ IL_003d: callvirt instance int32 IBar::Bar(int32)
+ IL_0042: ldc.i4.s 20
+ IL_0044: ceq
+ IL_0046: ldstr "Calling IBar.Bar on FooBar"
+ IL_004b: call void Test::Assert(bool,
+ string)
+ IL_0050: nop
+ IL_0051: ldstr "Calling IBlah.Blah on FooBar - expecting default m"
+ + "ethod on IBlah.Blah from Base. "
+ IL_0056: call void [mscorlib]System.Console::WriteLine(string)
+ IL_005b: nop
+ IL_005c: ldloc.3
+ IL_005d: ldc.i4.s 10
+ IL_005f: callvirt instance int32 IBlah::Blah(int32)
+ IL_0064: ldc.i4.s 16
+ IL_0066: ceq
+ IL_0068: ldstr "Calling IBlah.Blah on FooBar"
+ IL_006d: call void Test::Assert(bool,
+ string)
+ IL_0072: nop
+ IL_0073: ldstr "Calling FooBar.CallBlahProtected - expecting prote"
+ + "cted methods on interface can be called"
+ IL_0078: call void [mscorlib]System.Console::WriteLine(string)
+ IL_007d: nop
+ IL_007e: ldloc.0
+ IL_007f: callvirt instance int32 FooBar::CallBlahProtected()
+ IL_0084: ldc.i4.3
+ IL_0085: ceq
+ IL_0087: ldstr "Calling FooBar.CallBlahProtected"
+ IL_008c: call void Test::Assert(bool,
+ string)
+ IL_0091: nop
+ IL_0092: call int32 Test::Ret()
+ IL_0097: stloc.s V_4
+ IL_0099: br.s IL_009b
+
+ IL_009b: ldloc.s V_4
+ IL_009d: ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file simple.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj
new file mode 100644
index 0000000000..0bf910b766
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>simple</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="simple.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs
new file mode 100644
index 0000000000..0cf1be9a92
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs
@@ -0,0 +1,94 @@
+using System;
+
+interface IValue
+{
+ int GetValue();
+ void SetValue(int a);
+ int Add(int a);
+}
+
+// This class is only needed to spit out IL that assumes 'this' is an object (and therefore don't box)
+struct FooBarStruct_ : IValue
+{
+ public int GetValue()
+ {
+ return 0;
+ }
+
+ public void SetValue(int val)
+ {
+ }
+
+ public int Add(int a)
+ {
+ // Force cast and boxing
+ IValue valueIntf = this as IValue;
+ int val = valueIntf.GetValue();
+ val += a;
+ valueIntf.SetValue(val);
+ return val;
+ }
+}
+
+struct FooBarStruct : IValue
+{
+ public int _val;
+
+ public int GetValue()
+ {
+ return _val;
+ }
+
+ public void SetValue(int val)
+ {
+ _val = val;
+ }
+
+ public int Add(int a)
+ {
+ // Dummy
+ return 0;
+ }
+}
+
+class Program
+{
+ public static int Main()
+ {
+ FooBarStruct fooBar = new FooBarStruct();
+
+ fooBar._val = 10;
+
+ IValue foo = (IValue) fooBar;
+
+ Console.WriteLine("Calling IFoo.Foo on FooBarStruct");
+ Test.Assert(foo.Add(10) == 20, "Calling default method IValue.Add on FooBarStruct failed");
+ Test.Assert(fooBar.GetValue() == 10, "FooBarStruct value should remain unchanged");
+
+ return Test.Ret();
+ }
+}
+
+class Test
+{
+ private static bool Pass = true;
+
+ public static int Ret()
+ {
+ return Pass? 100 : 101;
+ }
+
+ public static void Assert(bool cond, string msg)
+ {
+ if (cond)
+ {
+ Console.WriteLine("PASS");
+ }
+ else
+ {
+ Console.WriteLine("FAIL: " + msg);
+ Pass = false;
+ }
+ }
+}
+
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il
new file mode 100644
index 0000000000..56c23f111e
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il
@@ -0,0 +1,252 @@
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly valuetypes
+{
+ .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.
+
+ // --- The following custom attribute is added automatically, do not uncomment -------
+ // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module valuetypes.exe
+// MVID: {E191F723-B724-4D70-B3A8-CEA89FD033D3}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01170000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class interface private abstract auto ansi IValue
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 GetValue() cil managed
+ {
+ } // end of method IValue::GetValue
+
+ .method public hidebysig newslot abstract virtual
+ instance void SetValue(int32 a) cil managed
+ {
+ } // end of method IValue::SetValue
+
+ .method public hidebysig newslot virtual
+ instance int32 Add(int32 a) cil managed
+ {
+ // Code size 26 (0x1a)
+ .maxstack 2
+ .locals init (int32 V_0,
+ int32 V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: call instance int32 IValue::GetValue()
+ IL_0007: stloc.0
+ IL_0008: ldloc.0
+ IL_0009: ldarg.1
+ IL_000a: add
+ IL_000b: stloc.0
+ IL_000c: ldarg.0
+ IL_000d: ldloc.0
+ IL_000e: call instance void IValue::SetValue(int32)
+ IL_0013: nop
+ IL_0014: ldloc.0
+ IL_0015: stloc.1
+ IL_0016: br.s IL_0018
+
+ IL_0018: ldloc.1
+ IL_0019: ret
+ } // end of method IValue::Add
+
+} // end of class IValue
+
+.class private sequential ansi sealed beforefieldinit FooBarStruct
+ extends [mscorlib]System.ValueType
+ implements IValue
+{
+ .field public int32 _val
+ .method public hidebysig newslot virtual final
+ instance int32 GetValue() cil managed
+ {
+ // Code size 12 (0xc)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldfld int32 FooBarStruct::_val
+ IL_0007: stloc.0
+ IL_0008: br.s IL_000a
+
+ IL_000a: ldloc.0
+ IL_000b: ret
+ } // end of method FooBarStruct::GetValue
+
+ .method public hidebysig newslot virtual final
+ instance void SetValue(int32 val) cil managed
+ {
+ // Code size 9 (0x9)
+ .maxstack 8
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldarg.1
+ IL_0003: stfld int32 FooBarStruct::_val
+ IL_0008: ret
+ } // end of method FooBarStruct::SetValue
+} // end of class FooBarStruct
+
+.class private auto ansi beforefieldinit Program
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ .maxstack 2
+ .locals init (valuetype FooBarStruct V_0,
+ class IValue V_1,
+ int32 V_2)
+ IL_0000: nop
+ IL_0001: ldloca.s V_0
+ IL_0003: initobj FooBarStruct
+ IL_0009: ldloca.s V_0
+ IL_000b: ldc.i4.s 10
+ IL_000d: stfld int32 FooBarStruct::_val
+ IL_0012: ldloc.0
+ IL_0013: box FooBarStruct
+ IL_0018: stloc.1
+ IL_0019: ldstr "Calling IFoo.Foo on FooBarStruct"
+ IL_001e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0023: nop
+ IL_0024: ldloc.1
+ IL_0025: ldc.i4.s 10
+ IL_0027: callvirt instance int32 IValue::Add(int32)
+ IL_002c: ldc.i4.s 20
+ IL_002e: ceq
+ IL_0030: ldstr "Calling default method IValue.Add on FooBarStruct "
+ + "failed"
+ IL_0035: call void Test::Assert(bool,
+ string)
+ IL_003a: nop
+ IL_003b: ldloca V_0
+ callvirt instance int32 FooBarStruct::GetValue()
+ ldc.i4.s 10
+ ceq
+ ldstr "FooBarStruct value should remain unchanged"
+ call void Test::Assert(bool,
+ string)
+ nop
+ call int32 Test::Ret()
+ ret
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Program::.ctor
+
+} // end of class Program
+
+.class private auto ansi beforefieldinit Test
+ extends [mscorlib]System.Object
+{
+ .field private static bool Pass
+ .method public hidebysig static int32 Ret() cil managed
+ {
+ // Code size 19 (0x13)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldsfld bool Test::Pass
+ IL_0006: brtrue.s IL_000c
+
+ IL_0008: ldc.i4.s 101
+ IL_000a: br.s IL_000e
+
+ IL_000c: ldc.i4.s 100
+ IL_000e: stloc.0
+ IL_000f: br.s IL_0011
+
+ IL_0011: ldloc.0
+ IL_0012: ret
+ } // end of method Test::Ret
+
+ .method public hidebysig static void Assert(bool cond,
+ string msg) cil managed
+ {
+ // Code size 47 (0x2f)
+ .maxstack 2
+ .locals init (bool V_0)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: stloc.0
+ IL_0003: ldloc.0
+ IL_0004: brfalse.s IL_0015
+
+ IL_0006: nop
+ IL_0007: ldstr "PASS"
+ IL_000c: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0011: nop
+ IL_0012: nop
+ IL_0013: br.s IL_002e
+
+ IL_0015: nop
+ IL_0016: ldstr "FAIL: "
+ IL_001b: ldarg.1
+ IL_001c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0021: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0026: nop
+ IL_0027: ldc.i4.0
+ IL_0028: stsfld bool Test::Pass
+ IL_002d: nop
+ IL_002e: ret
+ } // end of method Test::Assert
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test::.ctor
+
+ .method private hidebysig specialname rtspecialname static
+ void .cctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: stsfld bool Test::Pass
+ IL_0006: ret
+ } // end of method Test::.cctor
+
+} // end of class Test
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file valuetypes.res
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj
new file mode 100644
index 0000000000..12973e7559
--- /dev/null
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>valuetypes</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ <!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
+ <UseCustomILAsm>True</UseCustomILAsm>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="valuetypes.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il
index 1e481a350d..b885c241da 100644
--- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il
+++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il
@@ -14,11 +14,7 @@
.ver 4:0:0:0
}
-.assembly Except.exe{
- //This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration:
- //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )]
- .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )
-}
+.assembly Except.exe {}
.class Except {
diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il
index f248a93fb7..0cffb2bd13 100644
--- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il
+++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il
@@ -16,10 +16,7 @@
.ver 4:0:0:0
}
-.assembly FiltCatch.exe{
- //This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration:
- //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )]
- .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )}
+.assembly FiltCatch.exe{}
.class FiltCatch {
diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il
index 4168fcd40b..57f32f00e0 100644
--- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il
+++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il
@@ -16,10 +16,7 @@
.ver 4:0:0:0
}
-.assembly FiltFallThru{
-//This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration:
- //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )]
- .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )}
+.assembly FiltFallThru{}
.class FiltFallThru {
diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il
index 06d1338a8c..266bd38f70 100644
--- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il
+++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il
@@ -14,11 +14,7 @@
.ver 4:0:0:0
}
-.assembly Finally.exe{
-//This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration:
- //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )]
- .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )}
-
+.assembly Finally.exe{}
.class Finally {
.field static int32 iResult