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