summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2019-01-18 13:18:49 +0100
committerGitHub <noreply@github.com>2019-01-18 13:18:49 +0100
commite3932d49956acae70e0732ff3cfde7d8dc51db67 (patch)
treeaf81f360070c254d05cd1b2cd78a8440496a331d /src/vm
parent0a2596ce3d7fb0253f30b2461fa910c65840f9b3 (diff)
downloadcoreclr-e3932d49956acae70e0732ff3cfde7d8dc51db67.tar.gz
coreclr-e3932d49956acae70e0732ff3cfde7d8dc51db67.tar.bz2
coreclr-e3932d49956acae70e0732ff3cfde7d8dc51db67.zip
Handle complex constrained calls with default interface methods (#21978)
This adds handling for the interface dispatch corner case where: * We have a constrained callsite to a method on a generic interface in shared code * The callsite cannot be statically resolved because the result of dispatch depends on the generic context * At runtime, the dispatch resolves to a default interface method This would require us to have infrastructure to build "boxing thunks" - thunks that would box their first argument before dispatching to the default interface method implementation. Since this is a corner case and the fix is actually quite involved, we're making the runtime just throw in this situation. The test is written so that it should pass both if the runtime chooses to throw, or if the runtime makes the boxing thunk (we're not hardcoding the implementation limitation).
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/genericdict.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/vm/genericdict.cpp b/src/vm/genericdict.cpp
index 906f5c57fa..90af6395d7 100644
--- a/src/vm/genericdict.cpp
+++ b/src/vm/genericdict.cpp
@@ -1120,6 +1120,37 @@ Dictionary::PopulateEntry(
if (!pResolvedMD)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
+#if FEATURE_DEFAULT_INTERFACES
+ // If we resolved the constrained call on a value type into a method on a reference type, this is a
+ // default interface method implementation.
+ // In such case we would need to box the value type before we can dispatch to the implementation.
+ // This would require us to make a "boxing stub". For now we leave the boxing stubs unimplemented.
+ // It's not clear if anyone would need them and the implementation complexity is not worth it at this time.
+ if (!pResolvedMD->GetMethodTable()->IsValueType() && constraintType.GetMethodTable()->IsValueType())
+ {
+ SString assemblyName;
+
+ constraintType.GetMethodTable()->GetAssembly()->GetDisplayName(assemblyName);
+
+ SString strInterfaceName;
+ TypeString::AppendType(strInterfaceName, ownerType);
+
+ SString strMethodName;
+ TypeString::AppendMethod(strMethodName, pMethod, pMethod->GetMethodInstantiation());
+
+ SString strTargetClassName;
+ TypeString::AppendType(strTargetClassName, constraintType.GetMethodTable());
+
+ COMPlusThrow(
+ kNotSupportedException,
+ IDS_CLASSLOAD_UNSUPPORTED_DISPATCH,
+ strMethodName,
+ strInterfaceName,
+ strTargetClassName,
+ assemblyName);
+ }
+#endif
+
result = (CORINFO_GENERIC_HANDLE)pResolvedMD->GetMultiCallableAddrOfCode();
}
else