diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index ae68b714729953..b7890db6cffe04 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -196,7 +196,6 @@
-
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs
deleted file mode 100644
index ca9f73a5c667e8..00000000000000
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace System.Runtime.CompilerServices
-{
- ///
- /// Helpers that allows VM to call into ICastable methods without having to deal with RuntimeTypeHandle.
- /// RuntimeTypeHandle is a struct and is always passed in stack in x86, which our VM call helpers don't
- /// particularly like.
- ///
- internal static class ICastableHelpers
- {
- internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, [NotNullWhen(true)] out Exception? castError)
- {
- return castable.IsInstanceOfInterface(new RuntimeTypeHandle(type), out castError);
- }
-
- internal static RuntimeType GetImplType(ICastable castable, RuntimeType interfaceType)
- {
- return castable.GetImplType(new RuntimeTypeHandle(interfaceType)).GetRuntimeType();
- }
- }
-}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
index 88e07e8d388ced..3057f8d730d6de 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
@@ -682,7 +682,6 @@ internal unsafe struct MethodTable
// Types that require non-trivial interface cast have this bit set in the category
private const uint enum_flag_NonTrivialInterfaceCast = 0x00080000 // enum_flag_Category_Array
| 0x40000000 // enum_flag_ComObject
- | 0x00400000 // enum_flag_ICastable;
| 0x10000000 // enum_flag_IDynamicInterfaceCastable;
| 0x00040000; // enum_flag_Category_ValueType
diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props
index 1f513b1354d7ae..565cf03ee77368 100644
--- a/src/coreclr/clr.featuredefines.props
+++ b/src/coreclr/clr.featuredefines.props
@@ -2,7 +2,6 @@
true
true
- true
true
true
true
@@ -35,7 +34,6 @@
$(DefineConstants);FEATURE_PERFTRACING
$(DefineConstants);FEATURE_EVENTSOURCE_XPLAT
$(DefineConstants);FEATURE_TYPEEQUIVALENCE
- $(DefineConstants);FEATURE_ICASTABLE
$(DefineConstants);FEATURE_EH_FUNCLETS
$(DefineConstants);PROFILING_SUPPORTED
diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake
index 0a7a73bd4f1061..222eead41676c1 100644
--- a/src/coreclr/clrdefinitions.cmake
+++ b/src/coreclr/clrdefinitions.cmake
@@ -122,7 +122,6 @@ endif(CLR_CMAKE_TARGET_LINUX)
if(NOT CLR_CMAKE_TARGET_NETBSD)
add_definitions(-DFEATURE_HIJACK)
endif(NOT CLR_CMAKE_TARGET_NETBSD)
-add_definitions(-DFEATURE_ICASTABLE)
if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))
add_definitions(-DFEATURE_INTEROP_DEBUGGING)
endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))
diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h
index 03995176313c24..b2b983f1078a98 100644
--- a/src/coreclr/inc/dacvars.h
+++ b/src/coreclr/inc/dacvars.h
@@ -175,10 +175,6 @@ DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pIDynamicInterfaceCastableInterface, ::g_pIDynamicInterfaceCastableInterface)
-#ifdef FEATURE_ICASTABLE
-DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface)
-#endif // FEATURE_ICASTABLE
-
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pObjectFinalizerMD, ::g_pObjectFinalizerMD)
DEFINE_DACVAR(bool, dac__g_fProcessDetach, ::g_fProcessDetach)
diff --git a/src/coreclr/vm/.vscode/c_cpp_properties.json b/src/coreclr/vm/.vscode/c_cpp_properties.json
index 30f8ba3e8f5c44..c61fa10a35d428 100644
--- a/src/coreclr/vm/.vscode/c_cpp_properties.json
+++ b/src/coreclr/vm/.vscode/c_cpp_properties.json
@@ -53,7 +53,6 @@
"FEATURE_DEFAULT_INTERFACES",
"FEATURE_EVENT_TRACE=1",
"FEATURE_HIJACK",
- "FEATURE_ICASTABLE",
"FEATURE_INTEROP_DEBUGGING",
"FEATURE_ISYM_READER",
"FEATURE_MULTICASTSTUB_AS_IL",
diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp
index 125ba5f22cc618..5f31e0c9305e9d 100644
--- a/src/coreclr/vm/appdomain.cpp
+++ b/src/coreclr/vm/appdomain.cpp
@@ -1268,10 +1268,6 @@ void SystemDomain::LoadBaseSystemClasses()
}
#endif
- #ifdef FEATURE_ICASTABLE
- g_pICastableInterface = CoreLibBinder::GetClass(CLASS__ICASTABLE);
- #endif // FEATURE_ICASTABLE
-
#ifdef FEATURE_EH_FUNCLETS
g_pEHClass = CoreLibBinder::GetClass(CLASS__EH);
g_pExceptionServicesInternalCallsClass = CoreLibBinder::GetClass(CLASS__EXCEPTIONSERVICES_INTERNALCALLS);
diff --git a/src/coreclr/vm/callconvbuilder.cpp b/src/coreclr/vm/callconvbuilder.cpp
index d68ac7f023ec3d..58a14e3cc733f9 100644
--- a/src/coreclr/vm/callconvbuilder.cpp
+++ b/src/coreclr/vm/callconvbuilder.cpp
@@ -490,21 +490,14 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc*
BYTE* pData = NULL;
LONG cData = 0;
- bool nativeCallableInternalData = false;
HRESULT hr = pMD->GetCustomAttribute(WellKnownAttribute::UnmanagedCallersOnly, (const VOID **)(&pData), (ULONG *)&cData);
- if (hr == S_FALSE)
- {
- hr = pMD->GetCustomAttribute(WellKnownAttribute::NativeCallableInternal, (const VOID **)(&pData), (ULONG *)&cData);
- nativeCallableInternalData = SUCCEEDED(hr);
- }
-
IfFailThrow(hr);
_ASSERTE(cData > 0);
CustomAttributeParser ca(pData, cData);
- // UnmanagedCallersOnly and NativeCallableInternal each
+ // UnmanagedCallersOnly each
// have optional named arguments.
CaNamedArg namedArgs[2];
@@ -512,15 +505,8 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc*
CaType caCallConvs;
// Define attribute specific optional named properties
- if (nativeCallableInternalData)
- {
- namedArgs[0].InitI4FieldEnum("CallingConvention", "System.Runtime.InteropServices.CallingConvention", (ULONG)(CorPinvokeMap)0);
- }
- else
- {
- caCallConvs.Init(SERIALIZATION_TYPE_SZARRAY, SERIALIZATION_TYPE_TYPE, SERIALIZATION_TYPE_UNDEFINED, NULL, 0);
- namedArgs[0].Init("CallConvs", SERIALIZATION_TYPE_SZARRAY, caCallConvs);
- }
+ caCallConvs.Init(SERIALIZATION_TYPE_SZARRAY, SERIALIZATION_TYPE_TYPE, SERIALIZATION_TYPE_UNDEFINED, NULL, 0);
+ namedArgs[0].Init("CallConvs", SERIALIZATION_TYPE_SZARRAY, caCallConvs);
// Define common optional named properties
CaTypeCtor caEntryPoint(SERIALIZATION_TYPE_STRING);
@@ -542,25 +528,17 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc*
if (namedArgs[0].val.type.tag == SERIALIZATION_TYPE_UNDEFINED)
return false;
- CorInfoCallConvExtension callConvLocal;
- if (nativeCallableInternalData)
+ CallConvBuilder builder;
+ if (!TryGetCallingConventionFromTypeArray(&namedArgs[0].val, &builder))
{
- callConvLocal = (CorInfoCallConvExtension)(namedArgs[0].val.u4 << 8);
+ // We found a second base calling convention.
+ return false;
}
- else
- {
- CallConvBuilder builder;
- if (!TryGetCallingConventionFromTypeArray(&namedArgs[0].val, &builder))
- {
- // We found a second base calling convention.
- return false;
- }
- callConvLocal = builder.GetCurrentCallConv();
- if (callConvLocal == CallConvBuilder::UnsetValue)
- {
- callConvLocal = CallConv::GetDefaultUnmanagedCallingConvention();
- }
+ CorInfoCallConvExtension callConvLocal = builder.GetCurrentCallConv();
+ if (callConvLocal == CallConvBuilder::UnsetValue)
+ {
+ callConvLocal = CallConv::GetDefaultUnmanagedCallingConvention();
}
*pCallConv = callConvLocal;
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 0adc92baf3927c..745d762e832209 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -1124,15 +1124,6 @@ DEFINE_FIELD_U(_condition, ContractExceptionObject, _Condition)
DEFINE_CLASS(MODULEBASE, Reflection, Module)
-#ifdef FEATURE_ICASTABLE
-DEFINE_CLASS(ICASTABLE, CompilerServices, ICastable)
-
-DEFINE_CLASS(ICASTABLEHELPERS, CompilerServices, ICastableHelpers)
-DEFINE_METHOD(ICASTABLEHELPERS, ISINSTANCEOF, IsInstanceOfInterface, SM_ICastable_RtType_RefException_RetBool)
-DEFINE_METHOD(ICASTABLEHELPERS, GETIMPLTYPE, GetImplType, SM_ICastable_RtType_RetRtType)
-
-#endif // FEATURE_ICASTABLE
-
DEFINE_CLASS(STACKALLOCATEDBOX, CompilerServices, StackAllocatedBox`1)
DEFINE_CLASS(UTF8STRINGMARSHALLER, Marshalling, Utf8StringMarshaller)
diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp
index b365309257dbc3..876d2af8d63ec3 100644
--- a/src/coreclr/vm/jithelpers.cpp
+++ b/src/coreclr/vm/jithelpers.cpp
@@ -1080,35 +1080,6 @@ BOOL ObjIsInstanceOfCore(Object *pObject, TypeHandle toTypeHnd, BOOL throwCastEx
}
else
#endif // FEATURE_COMINTEROP
-#ifdef FEATURE_ICASTABLE
- // If type implements ICastable interface we give it a chance to tell us if it can be casted
- // to a given type.
- if (pMT->IsICastable())
- {
- // Make actual call to ICastableHelpers.IsInstanceOfInterface(obj, interfaceTypeObj, out exception)
- OBJECTREF exception = NULL;
- GCPROTECT_BEGIN(exception);
-
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICASTABLEHELPERS__ISINSTANCEOF);
-
- OBJECTREF managedType = toTypeHnd.GetManagedClassObject(); //GC triggers
-
- DECLARE_ARGHOLDER_ARRAY(args, 3);
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(obj);
- args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(managedType);
- args[ARGNUM_2] = PTR_TO_ARGHOLDER(&exception);
-
- CALL_MANAGED_METHOD(fCast, BOOL, args);
- INDEBUG(managedType = NULL); // managedType isn't protected during the call
-
- if (!fCast && throwCastException && exception != NULL)
- {
- RealCOMPlusThrow(exception);
- }
- GCPROTECT_END(); //exception
- }
- else
-#endif // FEATURE_ICASTABLE
if (pMT->IsIDynamicInterfaceCastable())
{
fCast = DynamicInterfaceCastable::IsInstanceOf(&obj, toTypeHnd, throwCastException);
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index 9c76cf0e7b08b0..315cd5481d3aec 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -4209,8 +4209,8 @@ TypeCompareState CEEInfo::compareTypesForCast(
else
#endif // FEATURE_COMINTEROP
- // If casting from ICastable or IDynamicInterfaceCastable, don't try to optimize
- if (fromHnd.GetMethodTable()->IsICastable() || fromHnd.GetMethodTable()->IsIDynamicInterfaceCastable())
+ // If casting from IDynamicInterfaceCastable, don't try to optimize
+ if (fromHnd.GetMethodTable()->IsIDynamicInterfaceCastable())
{
result = TypeCompareState::May;
}
diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h
index 9a409e100a1e56..0a9f50a7a912cd 100644
--- a/src/coreclr/vm/metasig.h
+++ b/src/coreclr/vm/metasig.h
@@ -577,12 +577,6 @@ DEFINE_METASIG(IM(PtrVoid_RetVoid, P(v), v))
DEFINE_METASIG_T(IM(PtrCopyConstructorCookie_RetVoid, P(g(COPY_CONSTRUCTOR_COOKIE)), v))
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
-
-#ifdef FEATURE_ICASTABLE
-DEFINE_METASIG_T(SM(ICastable_RtType_RefException_RetBool, C(ICASTABLE) C(CLASS) r(C(EXCEPTION)), F))
-DEFINE_METASIG_T(SM(ICastable_RtType_RetRtType, C(ICASTABLE) C(CLASS), C(CLASS)))
-#endif // FEATURE_ICASTABLE
-
DEFINE_METASIG_T(SM(IDynamicInterfaceCastable_RuntimeType_Bool_RetBool, C(IDYNAMICINTERFACECASTABLE) C(CLASS) F, F))
DEFINE_METASIG_T(SM(IDynamicInterfaceCastable_RuntimeType_RetRtType, C(IDYNAMICINTERFACECASTABLE) C(CLASS), C(CLASS)))
diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp
index 8b7239896a0ea6..d944116216523c 100644
--- a/src/coreclr/vm/method.cpp
+++ b/src/coreclr/vm/method.cpp
@@ -3517,14 +3517,6 @@ BOOL MethodDesc::HasUnmanagedCallersOnlyAttribute()
WellKnownAttribute::UnmanagedCallersOnly,
nullptr,
nullptr);
- if (hr != S_OK)
- {
- // See https://github.com/dotnet/runtime/issues/37622
- hr = GetCustomAttribute(
- WellKnownAttribute::NativeCallableInternal,
- nullptr,
- nullptr);
- }
return (hr == S_OK) ? TRUE : FALSE;
}
diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp
index 5e0ba6c09bfd5e..528b5950167e14 100644
--- a/src/coreclr/vm/methodtable.cpp
+++ b/src/coreclr/vm/methodtable.cpp
@@ -375,24 +375,6 @@ void MethodTable::SetComObjectType()
SetFlag(enum_flag_ComObject);
}
-#ifdef FEATURE_ICASTABLE
-void MethodTable::SetICastable()
-{
- LIMITED_METHOD_CONTRACT;
- SetFlag(enum_flag_ICastable);
-}
-#endif
-
-BOOL MethodTable::IsICastable()
-{
- LIMITED_METHOD_DAC_CONTRACT;
-#ifdef FEATURE_ICASTABLE
- return GetFlag(enum_flag_ICastable);
-#else
- return FALSE;
-#endif
-}
-
void MethodTable::SetIDynamicInterfaceCastable()
{
LIMITED_METHOD_CONTRACT;
@@ -499,42 +481,6 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
MethodTable *pServerMT = (*pServer)->GetMethodTable();
PREFIX_ASSUME(pServerMT != NULL);
-#ifdef FEATURE_ICASTABLE
- // In case of ICastable, instead of trying to find method implementation in the real object type
- // we call GetMethodDescForInterfaceMethod() again with whatever type it returns.
- // It allows objects that implement ICastable to mimic behavior of other types.
- if (pServerMT->IsICastable() &&
- !pItfMD->HasMethodInstantiation() &&
- !TypeHandle(pServerMT).CanCastTo(ownerType)) // we need to make sure object doesn't implement this interface in a natural way
- {
- GCStress::MaybeTrigger();
-
- // Make call to ICastableHelpers.GetImplType(obj, interfaceTypeObj)
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICASTABLEHELPERS__GETIMPLTYPE);
-
- OBJECTREF ownerManagedType = ownerType.GetManagedClassObject(); //GC triggers
-
- DECLARE_ARGHOLDER_ARRAY(args, 2);
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(*pServer);
- args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(ownerManagedType);
-
- OBJECTREF impTypeObj = NULL;
- CALL_MANAGED_METHOD_RETREF(impTypeObj, OBJECTREF, args);
-
- INDEBUG(ownerManagedType = NULL); //ownerManagedType wasn't protected during the call
- if (impTypeObj == NULL) // GetImplType returns default(RuntimeTypeHandle)
- {
- COMPlusThrow(kEntryPointNotFoundException);
- }
-
- ReflectClassBaseObject* resultTypeObj = ((ReflectClassBaseObject*)OBJECTREFToObject(impTypeObj));
- TypeHandle resultTypeHnd = resultTypeObj->GetType();
- MethodTable *pResultMT = resultTypeHnd.GetMethodTable();
-
- RETURN(pResultMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */));
- }
-#endif
-
// For IDynamicInterfaceCastable, instead of trying to find method implementation in the real object type
// we call GetInterfaceImplementation on the object and call GetMethodDescForInterfaceMethod
// with whatever type it returns.
@@ -1462,8 +1408,8 @@ BOOL MethodTable::CanCastTo(MethodTable* pTargetMT, TypeHandlePairList* pVisited
CanCastToClass(pTargetMT, pVisited);
// We only consider type-based conversion rules here.
- // Therefore a negative result cannot rule out convertibility for ICastable, IDynamicInterfaceCastable, and COM objects
- if (result || !(pTargetMT->IsInterface() && (this->IsComObjectType() || this->IsICastable() || this->IsIDynamicInterfaceCastable())))
+ // Therefore a negative result cannot rule out convertibility for IDynamicInterfaceCastable and COM objects
+ if (result || !(pTargetMT->IsInterface() && (this->IsComObjectType() || this->IsIDynamicInterfaceCastable())))
{
CastCache::TryAddToCache(this, pTargetMT, (BOOL)result);
}
diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h
index 79334cb03201fd..9e209f7c5e50d2 100644
--- a/src/coreclr/vm/methodtable.h
+++ b/src/coreclr/vm/methodtable.h
@@ -1031,12 +1031,6 @@ class MethodTable
// mark the class type as COM object class
void SetComObjectType();
-#ifdef FEATURE_ICASTABLE
- void SetICastable();
-#endif
-
- BOOL IsICastable(); // This type implements ICastable interface
-
void SetIDynamicInterfaceCastable();
BOOL IsIDynamicInterfaceCastable();
@@ -3697,7 +3691,7 @@ public :
enum_flag_HasFinalizer = 0x00100000, // instances require finalization. GC depends on this bit.
enum_flag_Collectible = 0x00200000, // GC depends on this bit.
- enum_flag_ICastable = 0x00400000, // class implements ICastable interface
+ // enum_flag_unused = 0x00400000,
#ifdef FEATURE_64BIT_ALIGNMENT
enum_flag_RequiresAlign8 = 0x00800000, // Type requires 8-byte alignment (only set on platforms that require this and don't get it implicitly)
@@ -3717,7 +3711,6 @@ public :
// Types that require non-trivial interface cast have this bit set in the category
enum_flag_NonTrivialInterfaceCast = enum_flag_Category_Array
| enum_flag_ComObject
- | enum_flag_ICastable
| enum_flag_IDynamicInterfaceCastable
| enum_flag_Category_ValueType
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index 6faa9972c3332f..ebe68bafaad892 100644
--- a/src/coreclr/vm/methodtablebuilder.cpp
+++ b/src/coreclr/vm/methodtablebuilder.cpp
@@ -1998,13 +1998,6 @@ MethodTableBuilder::BuildMethodTableThrowing(
if (!IsValueClass())
{
-#ifdef FEATURE_ICASTABLE
- if (g_pICastableInterface != NULL && pMT->CanCastToInterface(g_pICastableInterface))
- {
- pMT->SetICastable();
- }
-#endif // FEATURE_ICASTABLE
-
if (g_pIDynamicInterfaceCastableInterface != NULL && pMT->CanCastToInterface(g_pIDynamicInterfaceCastableInterface))
{
pMT->SetIDynamicInterfaceCastable();
diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp
index de1f7fd09007ba..3fbeffa8620fcb 100644
--- a/src/coreclr/vm/prestub.cpp
+++ b/src/coreclr/vm/prestub.cpp
@@ -2662,7 +2662,7 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method
{
pDispatchingMT = curobj->GetMethodTable();
- if (pDispatchingMT->IsICastable() || pDispatchingMT->IsIDynamicInterfaceCastable())
+ if (pDispatchingMT->IsIDynamicInterfaceCastable())
{
MethodTable* pMDMT = pMD->GetMethodTable();
TypeHandle objectType(pDispatchingMT);
@@ -2672,7 +2672,7 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method
INDEBUG(curobj = NULL); // curobj is unprotected and CanCastTo() can trigger GC
if (!objectType.CanCastTo(methodType))
{
- // Apparently ICastable magic was involved when we chose this method to be called
+ // Apparently IDynamicInterfaceCastable magic was involved when we chose this method to be called
// that's why we better stick to the MethodTable it belongs to, otherwise
// DoPrestub() will fail not being able to find implementation for pMD in pDispatchingMT.
@@ -3534,7 +3534,7 @@ static PCODE getHelperForStaticBase(Module * pModule, CORCOMPILE_FIXUP_BLOB_KIND
bool threadStatic = (kind == ENCODE_THREAD_STATIC_BASE_NONGC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER);
CorInfoHelpFunc helper;
-
+
if (threadStatic)
{
if (GCStatic)
diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp
index 7ff76d014a4ec9..ebd5310e40e6dc 100644
--- a/src/coreclr/vm/vars.cpp
+++ b/src/coreclr/vm/vars.cpp
@@ -72,11 +72,6 @@ GPTR_IMPL(MethodTable, g_pBaseCOMObject);
#endif
GPTR_IMPL(MethodTable, g_pIDynamicInterfaceCastableInterface);
-
-#ifdef FEATURE_ICASTABLE
-GPTR_IMPL(MethodTable, g_pICastableInterface);
-#endif // FEATURE_ICASTABLE
-
GPTR_IMPL(MethodDesc, g_pObjectFinalizerMD);
GPTR_IMPL(Thread,g_pFinalizerThread);
diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp
index 5814aa1ee83483..528d513e9d7b3f 100644
--- a/src/coreclr/vm/vars.hpp
+++ b/src/coreclr/vm/vars.hpp
@@ -350,11 +350,6 @@ GPTR_DECL(MethodTable, g_pBaseCOMObject);
#endif
GPTR_DECL(MethodTable, g_pIDynamicInterfaceCastableInterface);
-
-#ifdef FEATURE_ICASTABLE
-GPTR_DECL(MethodTable, g_pICastableInterface);
-#endif // FEATURE_ICASTABLE
-
GPTR_DECL(MethodDesc, g_pObjectFinalizerMD);
#ifdef FEATURE_INTEROP_DEBUGGING
diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp
index 5f7754e3f808f4..44bbb7e15d8615 100644
--- a/src/coreclr/vm/virtualcallstub.cpp
+++ b/src/coreclr/vm/virtualcallstub.cpp
@@ -1570,7 +1570,6 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite,
#if defined(_DEBUG)
if (!objectType->IsComObjectType()
- && !objectType->IsICastable()
&& !objectType->IsIDynamicInterfaceCastable())
{
CONSISTENCY_CHECK(!MethodTable::GetMethodDescForSlotAddress(target)->IsGenericMethodDefinition());
@@ -1989,41 +1988,6 @@ VirtualCallStubManager::Resolver(
fShouldPatch = TRUE;
}
#endif // FEATURE_COMINTEROP
-#ifdef FEATURE_ICASTABLE
- else if (pMT->IsICastable() && protectedObj != NULL && *protectedObj != NULL)
- {
- GCStress::MaybeTrigger();
-
- // In case of ICastable, instead of trying to find method implementation in the real object type
- // we call Resolver() again with whatever type it returns.
- // It allows objects that implement ICastable to mimic behavior of other types.
- MethodTable * pTokenMT = GetTypeFromToken(token);
-
- // Make call to ICastableHelpers.GetImplType(this, interfaceTypeObj)
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICASTABLEHELPERS__GETIMPLTYPE);
-
- OBJECTREF tokenManagedType = pTokenMT->GetManagedClassObject(); //GC triggers
-
- DECLARE_ARGHOLDER_ARRAY(args, 2);
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(*protectedObj);
- args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(tokenManagedType);
-
- OBJECTREF impTypeObj = NULL;
- CALL_MANAGED_METHOD_RETREF(impTypeObj, OBJECTREF, args);
-
- INDEBUG(tokenManagedType = NULL); //tokenManagedType wasn't protected during the call
- if (impTypeObj == NULL) // GetImplType returns default(RuntimeTypeHandle)
- {
- COMPlusThrow(kEntryPointNotFoundException);
- }
-
- ReflectClassBaseObject* resultTypeObj = ((ReflectClassBaseObject*)OBJECTREFToObject(impTypeObj));
- TypeHandle resultTypeHnd = resultTypeObj->GetType();
- MethodTable *pResultMT = resultTypeHnd.GetMethodTable();
-
- return Resolver(pResultMT, token, protectedObj, ppTarget, throwOnConflict);
- }
-#endif // FEATURE_ICASTABLE
else if (pMT->IsIDynamicInterfaceCastable()
&& protectedObj != NULL
&& *protectedObj != NULL
@@ -2234,8 +2198,7 @@ VirtualCallStubManager::GetTarget(
// No match, now do full resolve
BOOL fPatch;
- // TODO: passing NULL as protectedObj here can lead to incorrect behavior for ICastable objects
- // We need to review if this is the case and refactor this code if we want ICastable to become officially supported
+ // TODO: passing NULL as protectedObj here can lead to incorrect behavior for IDynamicInterfaceCastable objects
fPatch = Resolver(pMT, token, NULL, &target, throwOnConflict);
_ASSERTE(!throwOnConflict || target != (PCODE)NULL);
@@ -3814,8 +3777,7 @@ MethodDesc *VirtualCallStubManagerManager::Entry2MethodDesc(
DispatchToken token(VirtualCallStubManager::GetTokenFromStubQuick(pMgr, stubStartAddress, sk));
PCODE target = (PCODE)NULL;
- // TODO: passing NULL as protectedObj here can lead to incorrect behavior for ICastable objects
- // We need to review if this is the case and refactor this code if we want ICastable to become officially supported
+ // TODO: passing NULL as protectedObj here can lead to incorrect behavior for IDynamicInterfaceCastable objects
VirtualCallStubManager::Resolver(pMT, token, NULL, &target, TRUE /* throwOnConflict */);
return pMT->GetMethodDescForSlotAddress(target);
diff --git a/src/coreclr/vm/wellknownattributes.h b/src/coreclr/vm/wellknownattributes.h
index 85a747b2c9a948..aa7b9396149f4d 100644
--- a/src/coreclr/vm/wellknownattributes.h
+++ b/src/coreclr/vm/wellknownattributes.h
@@ -29,7 +29,6 @@ enum class WellKnownAttribute : DWORD
ManagedToNativeComInteropStub,
UnmanagedCallConv,
UnmanagedCallersOnly,
- NativeCallableInternal, // This is needed to support MCG scenarios
TypeIdentifier,
UnmanagedFunctionPointer,
ThreadStatic,
@@ -92,8 +91,6 @@ inline const char *GetWellKnownAttributeName(WellKnownAttribute attribute)
return "System.Runtime.InteropServices.UnmanagedCallConvAttribute";
case WellKnownAttribute::UnmanagedCallersOnly:
return "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute";
- case WellKnownAttribute::NativeCallableInternal:
- return "System.Runtime.InteropServices.NativeCallableInternalAttribute";
case WellKnownAttribute::TypeIdentifier:
return "System.Runtime.InteropServices.TypeIdentifierAttribute";
case WellKnownAttribute::UnmanagedFunctionPointer:
diff --git a/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml
index 6ee3efba01f6e4..413297c1857c92 100644
--- a/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml
+++ b/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml
@@ -5,10 +5,6 @@
CP0001
T:Internal.Console
-
- CP0001
- T:System.Runtime.CompilerServices.ICastable
-
CP0002
F:System.Resources.ResourceManager.BaseNameField
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 412fb8ba8b8644..d920dc227a376e 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -855,7 +855,6 @@
-
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs
deleted file mode 100644
index ae117637668eb2..00000000000000
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace System.Runtime.CompilerServices
-{
- ///
- /// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the
- /// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its
- /// interface map.
- ///
- public interface ICastable
- {
- // This is called if casting this object to the given interface type would otherwise fail. Casting
- // here means the IL isinst and castclass instructions in the case where they are given an interface
- // type as the target type.
- //
- // A return value of true indicates the cast is valid.
- //
- // If false is returned when this is called as part of a castclass then the usual InvalidCastException
- // will be thrown unless an alternate exception is assigned to the castError output parameter. This
- // parameter is ignored on successful casts or during the evaluation of an isinst (which returns null
- // rather than throwing on error).
- //
- // No exception should be thrown from this method (it will cause unpredictable effects, including the
- // possibility of an immediate failfast).
- //
- // The results of this call are not cached, so it is advisable to provide a performant implementation.
- //
- // The results of this call should be invariant for the same class, interface type pair. That is
- // because this is the only guard placed before an interface invocation at runtime. If a type decides
- // it no longer wants to implement a given interface it has no way to synchronize with callers that
- // have already cached this relationship and can invoke directly via the interface pointer.
- bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, [NotNullWhen(true)] out Exception? castError);
-
- // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find
- // the given interface type in the interface map of this object.
- //
- // It allows the implementor to return an alternate class type which does implement the interface. The
- // interface lookup shall be performed again on this type (failure to find the interface this time
- // resulting in a fail fast) and the corresponding implemented method on that class called instead.
- //
- // Naturally, since the call is dispatched to a method on a class which does not match the type of the
- // this pointer, extreme care must be taken in the implementation of the interface methods of this
- // surrogate type.
- //
- // No exception should be thrown from this method (it will cause unpredictable effects, including the
- // possibility of an immediate failfast).
- //
- // There is no error path defined here. By construction all interface dispatches will already have
- // been verified via the castclass/isinst mechanism (and thus a call to IsInstanceOfInterface above)
- // so this method is expected to succeed in all cases. The contract for interface dispatch does not
- // include any errors from the infrastructure, of which this is a part.
- //
- // The results of this lookup are cached so computation of the result is not as perf-sensitive as
- // IsInstanceOfInterface.
- RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType);
- }
-}
diff --git a/src/tests/Interop/ICastable/Castable.cs b/src/tests/Interop/ICastable/Castable.cs
deleted file mode 100644
index fcefb7e025e160..00000000000000
--- a/src/tests/Interop/ICastable/Castable.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using Xunit;
-
-public interface IRetArg
-{
- T ReturnArg(T t);
-}
-
-public interface IRetThis
-{
- IRetThis ReturnThis();
- Type GetMyType();
-}
-
-
-public interface IUnimplemented
-{
- void UnimplementedMethod();
-}
-
-public interface IExtra
-{
- int InnocentMethod();
-}
-
-public class CastableException : Exception {};
-
-
-public class RetArgImpl: IRetArg
-{
- public string ReturnArg(string t)
- {
- Console.WriteLine("ReturnArg has been called.");
- return t;
- }
-}
-
-public class GenRetArgImpl: IRetArg
-{
- public T ReturnArg(T t)
- {
- Console.WriteLine(String.Format("Generic ReturnArg has been called. My type is {0}", GetType()));
- return t;
- }
-}
-
-
-public class RetThisImpl: IRetThis
-{
- public IRetThis ReturnThis()
- {
- Console.WriteLine("RetThis has been called.");
- return this;
- }
-
- public Type GetMyType()
- {
- Console.WriteLine(String.Format("GetMyType has been called. My type is {0}", GetType()));
- return GetType();
- }
-}
-
-
-public class Castable : ICastable, IExtra
-{
- private Dictionary _interface2impl;
-
- public Castable(Dictionary interface2impl)
- {
- _interface2impl = interface2impl;
- }
-
- public bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError)
- {
- Console.WriteLine(String.Format("IsInstanceOfInterface has been called for type {0}", Type.GetTypeFromHandle(interfaceType)));
- if (_interface2impl == null)
- {
- castError = new CastableException();
- return false;
- }
- castError = null;
- return _interface2impl.ContainsKey(Type.GetTypeFromHandle(interfaceType));
- }
-
- public RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType)
- {
- Console.WriteLine(String.Format("GetImplType has been called for type {0}", Type.GetTypeFromHandle(interfaceType)));
- return _interface2impl[Type.GetTypeFromHandle(interfaceType)].TypeHandle;
- }
-
- public int InnocentMethod()
- {
- Console.WriteLine(String.Format("InnocentMethod has been called. My type is {0}", GetType()));
- return 3;
- }
-}
-
-public class BadCastable : ICastable
-{
- public bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError)
- {
- castError = null;
- return true;
- }
-
- public RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType)
- {
- return default(RuntimeTypeHandle);
- }
-}
-
-public class CastableTests
-{
- public static void Assert(bool value, string message)
- {
- Xunit.Assert.True(value, message);
- }
-
- [Fact]
- [SkipOnMono("ICastable is unsupported on Mono")]
- public static void Test()
- {
- //Console.WriteLine("Execution started. Attach debugger and press enter.");
- //Console.ReadLine();
-
- try
- {
- object implProxy = new Castable(
- new Dictionary()
- {
- { typeof(IRetArg), typeof(RetArgImpl) },
- { typeof(IRetArg), typeof(GenRetArgImpl) },
- { typeof(IRetThis), typeof(RetThisImpl) },
- { typeof(IExtra), null }, //we should never use it
- }
- );
-
- // testing simple cases
- Assert(implProxy is IRetThis, "implProxy should be castable to IRetThis via is");
- Assert(!(implProxy is IUnimplemented), "implProxy should not be castable to IUnimplemented via is");
- Assert((implProxy as IRetThis) != null, "implProxy should be castable to IRetThis is as");
- Assert((implProxy as IUnimplemented) == null, "implProxy should not be castable to IUnimplemented is as");
- var retThis = (IRetThis)implProxy;
- Assert(object.ReferenceEquals(retThis.ReturnThis(), implProxy), "RetThis should return implProxy");
- Assert(retThis.GetMyType() == typeof(Castable), "GetMyType should return typeof(Castable)");
-
- Assert(!(implProxy is IUnimplemented), "implProxy should not be castable to IUnimplemented via is");
- Assert((implProxy as IUnimplemented) == null, "implProxy should not be castable to IUnimplemented via as");
-
-
- // testing generics
- IRetArg retArgStr = (IRetArg)implProxy;
- Assert(retArgStr.ReturnArg("hohoho") == "hohoho", "retArgStr.ReturnArg() should return arg");
-
- IRetArg retArgInt = (IRetArg)implProxy;
- Assert(retArgInt.ReturnArg(42) == 42, "retArgInt.ReturnArg() should return arg");
-
-
- // testing Castable implementing other interfaces
- var extra = (IExtra)implProxy;
- Assert(extra.InnocentMethod() == 3, "InnocentMethod() should be called on Castable and return 3");
-
- // testing error handling
- try
- {
- var _ = (IUnimplemented)implProxy;
- Assert(false, "pProxy should not be castable to I1");
- }
- catch (InvalidCastException) {}
-
- object nullCastable = new Castable(null);
- try
- {
- var _ = (IRetThis)nullCastable;
- Assert(false, "Exceptions should be thrown from IsInstanceOfInterface");
- }
- catch (CastableException) {}
-
- Assert(!(nullCastable is IRetThis), "null castable shouldn't be allowed to be casted to anything");
-
- var shouldBeNull = nullCastable as IRetThis;
- Assert(shouldBeNull == null, "shouldBeNull should be assigned null");
-
- object badCastable = new BadCastable();
- try
- {
- var r = (IRetThis)badCastable;
- r.ReturnThis();
- Assert(false, "Exceptions should be thrown from ReturnThis()");
- }
- catch (EntryPointNotFoundException) {}
-
- //delegate testing
- Func fInt = new Func(extra.InnocentMethod);
- Assert(fInt() == 3, "Delegate call to InnocentMethod() should return 3");
-
- Func func = new Func(retThis.ReturnThis);
- Assert(object.ReferenceEquals(func(), implProxy), "Delegate call to ReturnThis() should return this");
- }
- catch (Exception e)
- {
- Assert(false, e.ToString());
- }
- }
-}
diff --git a/src/tests/Interop/ICastable/Castable.csproj b/src/tests/Interop/ICastable/Castable.csproj
deleted file mode 100644
index ff9fd9f5783095..00000000000000
--- a/src/tests/Interop/ICastable/Castable.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- true
- true
-
-
-
-
-
-
diff --git a/src/tests/Interop/ICastable/ICastable.CoreLib.csproj b/src/tests/Interop/ICastable/ICastable.CoreLib.csproj
deleted file mode 100644
index 49492925b187cd..00000000000000
--- a/src/tests/Interop/ICastable/ICastable.CoreLib.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
- true
- Library
- SharedLibrary
-
- System.Private.CoreLib
- disable
- $(NoWarn);nullable
-
-
-
-
-
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index a0410d57e0b9cf..8ff9e6ea7e8a19 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -1466,9 +1466,6 @@
Not supported on Mono
-
- needs triage
-
https://github.com/dotnet/runtime/issues/34072