Put default interfaces behind a define (#15358)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Tue, 5 Dec 2017 10:37:43 +0000 (11:37 +0100)
committerGitHub <noreply@github.com>
Tue, 5 Dec 2017 10:37:43 +0000 (11:37 +0100)
This is needed so that we can turn default interfaces off in release branches.

I can't find a central location where the PRERELEASE flag could be defined because native and managed builds seem to be completely disconnected.

To limit the risk of only flipping the flag in one build type, I'm adding a test that verifies being able to load an interface with default methods matches what RuntimeFeature says.

16 files changed:
clr.defines.targets
clrdefinitions.cmake
dir.props
src/inc/clrconfigvalues.h
src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs
src/vm/classcompat.cpp
src/vm/methodtablebuilder.cpp
tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj
tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj
tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.il [new file with mode: 0644]
tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.ilproj [new file with mode: 0644]

index 7dc442c..b9f159e 100644 (file)
@@ -1,4 +1,10 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+    <!-- Features we're currently flighting, but don't intend to ship in officially supported releases -->
+    <PropertyGroup Condition="'$(IsPrerelease)' == 'true'">
+        <FeatureDefaultInterfaces>true</FeatureDefaultInterfaces>
+    </PropertyGroup>
+
     <PropertyGroup>
         <DefineConstants Condition="'$(FeatureAppX)' == 'true'">$(DefineConstants);FEATURE_APPX</DefineConstants>
         <DefineConstants Condition="'$(FeatureArrayStubAsIL)' == 'true'">$(DefineConstants);FEATURE_ARRAYSTUB_AS_IL</DefineConstants>
@@ -17,6 +23,7 @@
         <DefineConstants Condition="'$(FeatureXplatEventSource)' == 'true'">$(DefineConstants);FEATURE_EVENTSOURCE_XPLAT</DefineConstants>
         <DefineConstants Condition="'$(FeatureUseLcid)' == 'true'">$(DefineConstants);FEATURE_USE_LCID</DefineConstants>
         <DefineConstants Condition="'$(FeatureWin32Registry)' == 'true'">$(DefineConstants);FEATURE_WIN32_REGISTRY</DefineConstants>
+        <DefineConstants Condition="'$(FeatureDefaultInterfaces)' == 'true'">$(DefineConstants);FEATURE_DEFAULT_INTERFACES</DefineConstants>
 
         <DefineConstants Condition="'$(ProfilingSupportedBuild)' == 'true'">$(DefineConstants);PROFILING_SUPPORTED</DefineConstants>
 
index 2ab424f..5e12ca1 100644 (file)
@@ -1,5 +1,14 @@
 include(clrfeatures.cmake)
 
+# If set, indicates that this is not an officially supported release
+# Keep in sync with IsPrerelease in dir.props
+set(PRERELEASE 1)
+
+# Features we're currently flighting, but don't intend to ship in officially supported releases
+if (PRERELEASE)
+  add_definitions(-DFEATURE_DEFAULT_INTERFACES=1)  
+endif (PRERELEASE)
+
 if (CLR_CMAKE_TARGET_ARCH_AMD64)
   if (CLR_CMAKE_PLATFORM_UNIX)
     add_definitions(-DDBG_TARGET_AMD64_UNIX)
index 56ee07c..fa46fc3 100644 (file)
--- a/dir.props
+++ b/dir.props
     <PackageThirdPartyNoticesFile>$(ProjectDir)THIRD-PARTY-NOTICES.TXT</PackageThirdPartyNoticesFile>
     <SyncInfoDirectory>$(BaseIntermediateOutputPath)</SyncInfoDirectory>
 
+    <!-- If true, indicates that this is not an officially supported release -->
+    <!-- It is important to flip this to false in official release branches -->
+    <!-- Keep it in sync with PRERELEASE in clrdefinitions.cmake -->
+    <IsPrerelease>true</IsPrerelease>
+
     <!-- This should be kept in sync with package details in src/.nuget/init/project.json -->
     <RuntimeIdGraphDefinitionVersion>1.0.2-beta-24224-02</RuntimeIdGraphDefinitionVersion>
     <RuntimeIdGraphDefinitionFile>$(PackagesDir)/microsoft.netcore.platforms/$(RuntimeIdGraphDefinitionVersion)/runtime.json</RuntimeIdGraphDefinitionFile>
index 6ebf948..24a18f1 100644 (file)
@@ -874,7 +874,6 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation, W("EXPERIMENTAL_TieredCo
 // TypeLoader
 // 
 CONFIG_DWORD_INFO(INTERNAL_TypeLoader_InjectInterfaceDuplicates, W("INTERNAL_TypeLoader_InjectInterfaceDuplicates"), 0, "Injects duplicates in interface map for all types.")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TypeLoader_DefaultInterfaces, W("UNSUPPORTED_TypeLoader_DefaultInterfaces"), 0, "Enables support for default interfaces.")
 
 // 
 // Virtual call stubs
index 4978b09..c6a97ec 100644 (file)
@@ -11,9 +11,12 @@ namespace System.Runtime.CompilerServices
         /// </summary>
         public const string PortablePdb = nameof(PortablePdb);
 
+#if FEATURE_DEFAULT_INTERFACES
+        /// <summary>
         /// Indicates that this version of runtime supports default interface method implementations.
         /// </summary>
         public const string DefaultImplementationsOfInterfaces = nameof(DefaultImplementationsOfInterfaces);
+#endif
 
         /// <summary>
         /// Checks whether a certain feature is supported by the Runtime.
@@ -23,7 +26,9 @@ namespace System.Runtime.CompilerServices
             switch (feature)
             {
                 case PortablePdb:
+#if FEATURE_DEFAULT_INTERFACES
                 case DefaultImplementationsOfInterfaces:
+#endif
                     return true;
             }
 
index fb48a15..af4c0d6 100644 (file)
@@ -2612,12 +2612,13 @@ VOID    MethodTableBuilder::EnumerateClassMethods()
             }
         }
 
+#ifndef FEATURE_DEFAULT_INTERFACES
         // Some interface checks.
         if (fIsClassInterface)
         {
             if (IsMdVirtual(dwMemberAttrs))
             {
-                if (!IsMdAbstract(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
+                if (!IsMdAbstract(dwMemberAttrs))
                 {
                     BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
                 }
@@ -2625,12 +2626,13 @@ VOID    MethodTableBuilder::EnumerateClassMethods()
             else
             {
                 // Instance field/method
-                if (!IsMdStatic(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
+                if (!IsMdStatic(dwMemberAttrs))
                 {
                     BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
                 }
             }
         }
+#endif
 
         // No synchronized methods in ValueTypes
         if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
index 1d524cc..9f4d2ca 100644 (file)
@@ -2900,12 +2900,13 @@ MethodTableBuilder::EnumerateClassMethods()
             }
         }
 
+#ifndef FEATURE_DEFAULT_INTERFACES
         // Some interface checks.
         if (fIsClassInterface)
         {
             if (IsMdVirtual(dwMemberAttrs))
             {
-                if (!IsMdAbstract(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
+                if (!IsMdAbstract(dwMemberAttrs))
                 {
                     BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
                 }
@@ -2913,12 +2914,13 @@ MethodTableBuilder::EnumerateClassMethods()
             else
             {
                 // Instance field/method
-                if (!IsMdStatic(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
+                if (!IsMdStatic(dwMemberAttrs))
                 {
                     BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
                 }
             }
         }
+#endif
 
         // No synchronized methods in ValueTypes
         if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
index de431d5..7a2fb51 100644 (file)
     <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>
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-    
+    <CLRTestPriority>0</CLRTestPriority>    
   </PropertyGroup>
 
   <ItemGroup>
index 78d9162..df375eb 100644 (file)
     <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>    
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-
   </PropertyGroup>
 
   <ItemGroup>
index 03db9c5..463e3ed 100644 (file)
     <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>
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-
   </PropertyGroup>
 
   <ItemGroup>
index 03f4842..eb7660b 100644 (file)
     <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>
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-
   </PropertyGroup>
 
   <ItemGroup>
index 7b6f274..a97596e 100644 (file)
     <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>
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-
   </PropertyGroup>
 
   <ItemGroup>
index aa2f06c..0446a78 100644 (file)
     <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>  
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-  
   </PropertyGroup>
 
   <ItemGroup>
index f928997..f190a75 100644 (file)
     <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>    
-
-    <CLRTestBatchPreCommands>
-<![CDATA[
-      $(CLRTestBatchPreCommands)
-set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </CLRTestBatchPreCommands>
-    <BashCLRTestPreCommands>
-<![CDATA[
-      $(BashCLRTestPreCommands)
-export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
-    ]]>
-    </BashCLRTestPreCommands>
-
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.il b/tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.il
new file mode 100644 (file)
index 0000000..56ff2e7
--- /dev/null
@@ -0,0 +1,73 @@
+// 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.
+
+//
+// Verifies that RuntimeFeature::IsSupported("DefaultImplementationsOfInterfaces") matches reality.
+// This needs to succeed no matter whether default interfaces are supported.
+//
+
+.assembly extern System.Runtime{}
+.assembly DefaultImplementationsOfInterfaces{}
+
+.class interface private abstract auto ansi DefaultInterface
+{
+  .method public hidebysig newslot virtual 
+          instance void  Method() cil managed
+  {
+    .maxstack  8
+    ret
+  }
+}
+
+.method private hidebysig static void TryLoadDefaultInterface() cil managed noinlining
+{
+    .maxstack  8
+    ldtoken    DefaultInterface
+    call       class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+    callvirt   instance string [System.Runtime]System.Object::ToString()
+    pop
+    ret
+}
+
+.method private hidebysig static bool  SupportsDefaultInterfaces() cil managed
+{
+    .maxstack  1
+    .try
+    {
+      call       void TryLoadDefaultInterface()
+      leave.s    Supports
+
+    }
+    catch [System.Runtime]System.TypeLoadException 
+    {
+      pop
+      leave.s    DoesNotSupport
+
+    }
+  Supports:
+    ldc.i4.1
+    ret
+
+  DoesNotSupport:
+    ldc.i4.0
+    ret
+  }
+
+.method private hidebysig static int32 
+        Main() cil managed
+{
+    .entrypoint
+    .maxstack  2
+    ldstr      "DefaultImplementationsOfInterfaces"
+    call       bool [System.Runtime]System.Runtime.CompilerServices.RuntimeFeature::IsSupported(string)
+    call       bool SupportsDefaultInterfaces()
+    beq        Good
+
+    ldc.i4.m1
+    ret
+
+  Good:
+    ldc.i4     100
+    ret
+}
diff --git a/tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.ilproj b/tests/src/baseservices/compilerservices/RuntimeFeature/DefaultImplementationsOfInterfaces.ilproj
new file mode 100644 (file)
index 0000000..56bfa03
--- /dev/null
@@ -0,0 +1,38 @@
+<?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>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A8E3EED5-E6C0-4976-AC7E-70691EA00C52}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>0</CLRTestPriority>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="DefaultImplementationsOfInterfaces.il" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup> 
+</Project>
\ No newline at end of file