diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index 44f4bc256f99ce..46e7452fad2c5f 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -36,6 +36,8 @@ configurations but their defaults might vary as any SDK can set the defaults dif | EnableGeneratedComInterfaceComImportInterop | System.Runtime.InteropServices.Marshalling.EnableGeneratedComInterfaceComImportInterop | When set to true, enables casting source-generated COM object wrappers to built-in COM-based COM interfaces. | | _UseManagedNtlm | System.Net.Security.UseManagedNtlm | When set to true, uses built-in managed implementation of NTLM and SPNEGO algorithm for HTTP, SMTP authentication, and NegotiateAuthentication API instead of system provided GSSAPI implementation. | | _ComObjectDescriptorSupport | System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported | When set to true, supports creating a TypeDescriptor based view of COM objects. | +| _DesignerHostSupport | System.ComponentModel.Design.IDesignerHost.IsSupported | When set to true, supports creating design components at runtime. | +| _DefaultValueAttributeSupport | System.ComponentModel.DefaultValueAttribute.IsSupported | When set to true, supports creating a DefaultValueAttribute at runtime. | Any feature-switch which defines property can be set in csproj file or on the command line as any other MSBuild property. Those without predefined property name diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index fb53eb78bfc8af..62a2b4d7fb7376 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -38,7 +38,6 @@ public AmbientValueAttribute(long value) { } public AmbientValueAttribute(object? value) { } public AmbientValueAttribute(float value) { } public AmbientValueAttribute(string? value) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public AmbientValueAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string value) { } public object? Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml index aac20beb79bab5..e796cac8f444c5 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -22,5 +22,12 @@ M:System.ComponentModel.TypeDescriptor.NodeFor(System.Object,System.Boolean) This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported=true. + + ILLink + IL2026 + member + M:System.ComponentModel.AmbientValueAttribute.#ctor(System.Type,System.String) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.Design.IDesignerHost.IsSupported=true. + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs index 53a43204668305..ae52e7ebc93846 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs @@ -24,12 +24,12 @@ public sealed class AmbientValueAttribute : Attribute /// specified value to the specified type, and using the U.S. English culture as the /// translation context. /// - [RequiresUnreferencedCode(TypeConverter.RequiresUnreferencedCodeMessage)] public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string value) { // The try/catch here is because attributes should never throw exceptions. We would fail to // load an otherwise normal class. + Debug.Assert(IDesignerHost.IsSupported, "Runtime instantiation of this attribute is not allowed with trimming."); if (!IDesignerHost.IsSupported) { return; @@ -37,7 +37,10 @@ public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemb try { - _value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value); + _value = TypeDescriptorGetConverter(type).ConvertFromInvariantString(value); + + [RequiresUnreferencedCode("AmbientValueAttribute usage of TypeConverter is not compatible with trimming.")] + static TypeConverter TypeDescriptorGetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) => TypeDescriptor.GetConverter(type); } catch { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs index 8ab34614a7ebde..46dbae0a74d49c 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs @@ -12,7 +12,10 @@ namespace System.ComponentModel.Design public interface IDesignerHost : IServiceContainer { [FeatureSwitchDefinition("System.ComponentModel.Design.IDesignerHost.IsSupported")] + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] +#pragma warning disable IL4000 internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.Design.IDesignerHost.IsSupported", out bool isSupported) ? isSupported : true; +#pragma warning restore IL4000 /// /// Gets or sets a value indicating whether the designer host diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml index 278ed933f07043..c0523c4d646dc0 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -22,5 +22,12 @@ M:System.StartupHookProvider.ProcessStartupHooks(System.String) This warning is left in the product so developers get an ILLink warning when trimming an app with System.StartupHookProvider.IsSupported=true. + + ILLink + IL2026 + member + M:System.ComponentModel.DefaultValueAttribute.#ctor(System.Type,System.String) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.DefaultValueAttribute.IsSupported=true. + diff --git a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs index 322a6ae242b051..3ab01cee369168 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs @@ -24,14 +24,16 @@ public class DefaultValueAttribute : Attribute private static object? s_convertFromInvariantString; [FeatureSwitchDefinition("System.ComponentModel.DefaultValueAttribute.IsSupported")] + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] +#pragma warning disable IL4000 internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.DefaultValueAttribute.IsSupported", out bool isSupported) ? isSupported : true; +#pragma warning restore IL4000 /// /// Initializes a new instance of the /// class, converting the specified value to the specified type, and using the U.S. English /// culture as the translation context. /// - [RequiresUnreferencedCode("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public DefaultValueAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string? value) @@ -39,9 +41,9 @@ public DefaultValueAttribute( // The null check and try/catch here are because attributes should never throw exceptions. // We would fail to load an otherwise normal class. + Debug.Assert(IsSupported, "Runtime instantiation of this attribute is not allowed with trimming."); if (!IsSupported) { - Debug.Assert(!IsSupported, "Runtime instantiation of this attribute is not allowed."); return; } @@ -69,7 +71,7 @@ public DefaultValueAttribute( _value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture); } - [RequiresUnreferencedCode("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] + [RequiresUnreferencedCode("DefaultValueAttribute usage of TypeConverter is not compatible with trimming.")] // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string) static bool TryConvertFromInvariantString( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type typeToConvert, diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 8b4ba90dc9b223..e8ef65ea314449 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -8047,7 +8047,6 @@ public DefaultValueAttribute(object? value) { } public DefaultValueAttribute(sbyte value) { } public DefaultValueAttribute(float value) { } public DefaultValueAttribute(string? value) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public DefaultValueAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string? value) { } [System.CLSCompliantAttribute(false)] public DefaultValueAttribute(ushort value) { } diff --git a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets index 4273b40c1a5d5f..d6d45f475fc33b 100644 --- a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets +++ b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets @@ -53,6 +53,8 @@ Copyright (c) .NET Foundation. All rights reserved. <_UseManagedNtlm Condition="'$(_UseManagedNtlm)' == '' and $(RuntimeIdentifier.StartsWith('linux'))">false <_ComObjectDescriptorSupport Condition="'$(_ComObjectDescriptorSupport)' == ''">false + <_DesignerHostSupport Condition="'$(_DesignerHostSupport)' == ''">false + <_DefaultValueAttributeSupport Condition="'$(_DefaultValueAttributeSupport)' == ''">false