Moves CurrentSystemTimeZone, ICastable, RegistryView and RegistryValueKind to shared...
authorMaryam Ariyan <maryam.ariyan@microsoft.com>
Thu, 7 Jun 2018 19:40:40 +0000 (12:40 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 7 Jun 2018 19:40:40 +0000 (12:40 -0700)
* Moves CurrentSystemTimeZone to shared completely

* Moves ICastable to shared

* Moves RegistryView and RegistryValueKind to shared

* Moves ICastableHelpers to its own file

15 files changed:
src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryValues.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryView.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs [new file with mode: 0644]
src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs
src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs [deleted file]
src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs [deleted file]
src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs [deleted file]
src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs [deleted file]
src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs [new file with mode: 0644]

index a6536c03f2c13bfa80e3eefd387d91767b721ba2..dd29c084afb163bef0717873fb3c8f7dd7c0c8c5 100644 (file)
   <Import Project="$(MSBuildThisFileDirectory)..\..\clr.defines.targets" />
   <!-- Sources -->
   <ItemGroup>
+    <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ICastableHelpers.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeDependencyAttribute.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\jithelpers.cs" />
-    <Compile Condition="'$(FeatureICastable)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ICastable.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ConditionalWeakTable.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncMethodBuilder.cs" />
   </ItemGroup>
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.CoreClrOverrides.cs" />
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.cs" />
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.Central.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\CurrentSystemTimeZone.Cache.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Object.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Array.cs" />
     <Compile Include="$(BclSourcesRoot)\System\ThrowHelper.cs" />
     <Compile Include="$(BclSourcesRoot)\Microsoft\Win32\Win32Native.cs" />
     <Compile Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\Registry.cs" />
     <Compile Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryKey.cs" />
-    <Compile Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryValueKind.cs" />
-    <Compile Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryView.cs" />
     <Compile Condition="'$(FeatureClassicCominterop)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\OAVariantLib.cs" />
   </ItemGroup>
   <ItemGroup>
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryValues.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryValues.cs
new file mode 100644 (file)
index 0000000..8a4b84d
--- /dev/null
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+internal partial class Interop
+{
+    internal partial class Kernel32
+    {
+        internal partial class RegistryValues
+        {
+            internal const int REG_NONE = 0;                // No value type
+            internal const int REG_SZ = 1;                  // Unicode nul terminated string
+            internal const int REG_EXPAND_SZ = 2;           // Unicode nul terminated string
+            // (with environment variable references)
+            internal const int REG_BINARY = 3;              // Free form binary
+            internal const int REG_DWORD = 4;               // 32-bit number
+            internal const int REG_MULTI_SZ = 7;            // Multiple Unicode strings
+            internal const int REG_QWORD = 11;             // 64-bit number
+        }
+    }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryView.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.RegistryView.cs
new file mode 100644 (file)
index 0000000..2e67868
--- /dev/null
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+internal partial class Interop
+{
+    internal partial class Kernel32
+    {
+        internal partial class RegistryView
+        {
+            internal const int KEY_WOW64_64KEY = 0x0100;
+            internal const int KEY_WOW64_32KEY = 0x0200;
+        }
+    }
+}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs
new file mode 100644 (file)
index 0000000..1d8d561
--- /dev/null
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace Microsoft.Win32
+{
+#if REGISTRY_ASSEMBLY
+    public
+#else
+    internal
+#endif
+    enum RegistryValueKind
+    {
+        String = Interop.Kernel32.RegistryValues.REG_SZ,
+        ExpandString = Interop.Kernel32.RegistryValues.REG_EXPAND_SZ,
+        Binary = Interop.Kernel32.RegistryValues.REG_BINARY,
+        DWord = Interop.Kernel32.RegistryValues.REG_DWORD,
+        MultiString = Interop.Kernel32.RegistryValues.REG_MULTI_SZ,
+        QWord = Interop.Kernel32.RegistryValues.REG_QWORD,
+        Unknown = 0,                          // REG_NONE is defined as zero but BCL
+        None = unchecked((int)0xFFFFFFFF), //  mistakenly overrode this value.  
+    }   // Now instead of using Interop.Kernel32.RegistryValues.REG_NONE we use "-1".
+}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs
new file mode 100644 (file)
index 0000000..3cc4a78
--- /dev/null
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Microsoft.Win32
+{
+#if REGISTRY_ASSEMBLY
+    public
+#else
+    internal
+#endif
+    enum RegistryView
+    {
+        Default = 0, // 0x0000 operate on the default registry view
+        Registry64 = Interop.Kernel32.RegistryView.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+        Registry32 = Interop.Kernel32.RegistryView.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+    };
+}
index 26dfbd82d51d1528e385b9dcee2f7159d8634f6b..98f9d1ebefa4911ca1c467aacf53c03ecb36ed8f 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\FixedBufferAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\FormattableStringFactory.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IAsyncStateMachine.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ICastable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IndexerNameAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\INotifyCompletion.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\InternalsVisibleToAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.OutputDebugString.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_IntPtr.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_NativeOverlapped.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.RegistryValues.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.RegistryView.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SECURITY_ATTRIBUTES.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SecurityOptions.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEndOfFile.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEnvironmentVariable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetThreadErrorMode.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetFilePointerEx.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WideCharToMultiByte.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Idna.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Normalization.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
-    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Ole32\Interop.CoCreateGuid.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFindHandle.Windows.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryView.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryValueKind.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
index bab6a92bf5537515a9efae133841581a4de6f7b4..8327bd2f4a633c0a651416a70562cd3611b1102b 100644 (file)
 **
 ============================================================*/
 
-using System;
-using System.Text;
 using System.Collections;
 using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
 
 namespace System
 {
@@ -193,5 +189,29 @@ namespace System
                 return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
             }
         }
+
+        private DaylightTime GetCachedDaylightChanges(int year)
+        {
+            Object objYear = (Object)year;
+
+            if (!m_CachedDaylightChanges.Contains(objYear))
+            {
+                DaylightTime currentDaylightChanges = CreateDaylightChanges(year);
+                lock (m_CachedDaylightChanges)
+                {
+                    if (!m_CachedDaylightChanges.Contains(objYear))
+                    {
+                        m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+                    }
+                }
+            }
+
+            return (DaylightTime)m_CachedDaylightChanges[objYear];
+        }
+
+        // The per-year information is cached in in this instance value. As a result it can
+        // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
+        private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
+
     } // class CurrentSystemTimeZone
 }
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs
new file mode 100644 (file)
index 0000000..37e7735
--- /dev/null
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+    /// <summary>
+    /// 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.
+    /// </summary>
+    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, 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);
+    }
+}
index 1df495e44747febfcf103f3911995ec9a638f091..f861e5f9b81733ffa4cef69be660cc6cffa44396 100644 (file)
@@ -1121,7 +1121,12 @@ namespace Microsoft.Win32
     }
 
     [Flags]
-    internal enum RegistryValueOptions
+#if REGISTRY_ASSEMBLY
+    public
+#else
+    internal
+#endif
+    enum RegistryValueOptions
     {
         None = 0,
         DoNotExpandEnvironmentNames = 1
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs
deleted file mode 100644 (file)
index 6e2a4f3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-
-namespace Microsoft.Win32
-{
-    internal enum RegistryValueKind
-    {
-        String = Win32Native.REG_SZ,
-        ExpandString = Win32Native.REG_EXPAND_SZ,
-        Binary = Win32Native.REG_BINARY,
-        DWord = Win32Native.REG_DWORD,
-        MultiString = Win32Native.REG_MULTI_SZ,
-        QWord = Win32Native.REG_QWORD,
-        Unknown = 0,                          // REG_NONE is defined as zero but BCL
-        None = unchecked((int)0xFFFFFFFF), //  mistakingly overrode this value.  
-    }   // Now instead of using Win32Native.REG_NONE we use "-1" and play games internally.
-}
-
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs
deleted file mode 100644 (file)
index e415865..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-//
-//
-//
-// Implements Microsoft.Win32.RegistryView
-//
-// ======================================================================================
-
-using System;
-
-namespace Microsoft.Win32
-{
-    internal enum RegistryView
-    {
-        Default = 0,                           // 0x0000 operate on the default registry view
-        Registry64 = Win32Native.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
-        Registry32 = Win32Native.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
-    };
-}
index 3545328f8aff0a6f3c95e532dab26c72de8a3d3e..9a2678fabdefc07eb18e9ac284ba53f5271876fd 100644 (file)
@@ -130,8 +130,6 @@ namespace Microsoft.Win32
                                                            KEY_CREATE_SUB_KEY)
                                                           &
                                                           (~SYNCHRONIZE));
-        internal const int KEY_WOW64_64KEY = 0x0100;     //
-        internal const int KEY_WOW64_32KEY = 0x0200;     //
         internal const int REG_OPTION_NON_VOLATILE = 0x0000;     // (default) keys are persisted beyond reboot/unload
         internal const int REG_OPTION_VOLATILE = 0x0001;     // All keys created by the function are volatile
         internal const int REG_OPTION_CREATE_LINK = 0x0002;     // They key is a symbolic link
diff --git a/src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs b/src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs
deleted file mode 100644 (file)
index 744c697..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections;
-using System.Globalization;
-
-namespace System
-{
-    internal partial class CurrentSystemTimeZone
-    {
-        private DaylightTime GetCachedDaylightChanges(int year)
-        {
-            Object objYear = (Object)year;
-
-            if (!m_CachedDaylightChanges.Contains(objYear))
-            {
-                DaylightTime currentDaylightChanges = CreateDaylightChanges(year);
-                lock (m_CachedDaylightChanges)
-                {
-                    if (!m_CachedDaylightChanges.Contains(objYear))
-                    {
-                        m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
-                    }
-                }
-            }
-
-            return (DaylightTime)m_CachedDaylightChanges[objYear];
-        }
-
-        // The per-year information is cached in in this instance value. As a result it can
-        // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
-        private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
-    }
-}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs
deleted file mode 100644 (file)
index e2b76ed..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-
-
-//
-// 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.
-//
-
-using System;
-
-namespace System.Runtime.CompilerServices
-{
-    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, 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);
-    }
-
-    /// <summary>
-    /// 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.
-    /// </summary>
-    internal class ICastableHelpers
-    {
-        internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, 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/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs
new file mode 100644 (file)
index 0000000..9343915
--- /dev/null
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+    
+    /// <summary>
+    /// 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.
+    /// </summary>
+    internal class ICastableHelpers
+    {
+        internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, 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();
+        }
+    }
+}
\ No newline at end of file