Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable default and ambient attribute at runtime with a feature switch #100416

Merged
merged 3 commits into from
Apr 5, 2024

Conversation

LakshanF
Copy link
Member

@LakshanF LakshanF commented Mar 28, 2024

Disable design time attributes being used at runtime via a feature switch.

@LakshanF LakshanF self-assigned this Mar 28, 2024
@LakshanF LakshanF marked this pull request as draft March 28, 2024 18:02
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-componentmodel
See info in area-owners.md if you want to be subscribed.

@@ -35,6 +39,12 @@ public class DefaultValueAttribute : Attribute
// The null check and try/catch here are because attributes should never throw exceptions.
// We would fail to load an otherwise normal class.

if (!IsSupported)
{
Debug.Assert(!IsSupported, "Runtime instantiation of this attribute is not allowed.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert vs. throw approaches - was the Assert approach taken to be backwards compatible here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, respecting the comments on the type so as not to throw

Debug.Assert(!IDesignerHost.IsSupported, "Runtime instantiation of this attribute is not allowed.");
return;
}

try
{
Value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this (and the case for DefaultValueAttribute below) causing an error at runtime or is this to help with linkability (e.g. #97842)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is to help with #97842 (trimming with the corresponding feature switch is set).

@@ -22,6 +23,9 @@ public class DefaultValueAttribute : Attribute
// Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache
private static object? s_convertFromInvariantString;

[FeatureSwitchDefinition("System.ComponentModel.DefaultValueAttribute.IsSupported")]
internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.DefaultValueAttribute.IsSupported", out bool isSupported) ? isSupported : true;
Copy link
Member

@steveharter steveharter Apr 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is made readonly then the JIT should be able to remove code as well (for cases when the trimmer isn't used). (requires adding a readonly field + a property)

@sbomer is my readonly comment above still applicable? Do we have guidance for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sanctioned pattern that should be optimizable by the JIT is a static bool property with a getter (see original design at https://github.com/dotnet/designs/blob/main/accepted/2020/feature-switch.md). I don't believe a field is necessary, but haven't checked the JIT codegen. @vitek-karas

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, in addition to perhaps supporting JIT, a static readonly field accessed by the property would cache the value, so AppContext.TryGetSwitch() doesn't get called every time (again, only for non-trimmed scenarios).


if (!IDesignerHost.IsSupported)
{
Debug.Assert(!IDesignerHost.IsSupported, "Runtime instantiation of this attribute is not allowed.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious - it feels weird asserting that the condition of the if is true in the true branch...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert is meant to give an indication of the problem of using this attribute when the feature switch is set. Throwing (with an appropriate message) here would be ideal but it seems prudent to respect the comments on the type. Consumers (like WinForms) could also generate a warning via its code generator when it detects use of this attribute at runtime if the feature switch is set.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is it supposed to be Debug.Assert(false)? Currently it seems like the assert will never fail.

@LakshanF LakshanF merged commit 92afc71 into dotnet:main Apr 5, 2024
148 of 150 checks passed
@LakshanF LakshanF deleted the DefaultValueFix branch April 5, 2024 21:00
matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
dotnet#100416)

* Disable default and ambient attribute at runtime with a feature switch

* throwing at the getter at runtime
@github-actions github-actions bot locked and limited conversation to collaborators May 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants