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

Fix InvariantGlobalization=false in a trimmed app #53453

Merged
merged 5 commits into from
Jun 8, 2021

Conversation

eerhardt
Copy link
Member

Move the LoadICU logic into a static ctor, so it runs early in the process, but not as part of querying the GlobalizationMode.Invariant property. This allows for LoadICU to still be invoked, even when the app is trimmed and GlobalizationMode.Invariant is hard-coded false by the linker.

While I was changing this code, I also removed the workaround in Browser builds for swallowing errors being returned from LoadICU.

Fix #49073
Fix #49391

Move the LoadICU logic into a static ctor, so it runs early in the process, but not as part of querying the GlobalizationMode.Invariant property. This allows for LoadICU to still be invoked, even when the app is trimmed and GlobalizationMode.Invariant is hard-coded by the linker.

While I was changing this code, I also removed the workaround in Browser builds for swallowing errors being returned from LoadICU.

Fix dotnet#49073
Fix dotnet#49391
@ghost
Copy link

ghost commented May 28, 2021

Tagging subscribers to this area: @tarekgh, @safern
See info in area-owners.md if you want to be subscribed.

Issue Details

Move the LoadICU logic into a static ctor, so it runs early in the process, but not as part of querying the GlobalizationMode.Invariant property. This allows for LoadICU to still be invoked, even when the app is trimmed and GlobalizationMode.Invariant is hard-coded false by the linker.

While I was changing this code, I also removed the workaround in Browser builds for swallowing errors being returned from LoadICU.

Fix #49073
Fix #49391

Author: eerhardt
Assignees: -
Labels:

area-System.Globalization

Milestone: -

Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

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

Added a minor comment and question, LGTM otherwise.

@@ -6,7 +6,7 @@
<method signature="System.Boolean IsEnabled(System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords)" body="stub" value="false" />
<method signature="System.Boolean IsEnabled(System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords,System.Diagnostics.Tracing.EventChannel)" body="stub" value="false" />
</type>
<type fullname="System.Globalization.GlobalizationMode">
<type fullname="System.Globalization.GlobalizationMode/Settings">
Copy link
Contributor

Choose a reason for hiding this comment

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

This effectively removes Invariant = true dependencies trimming. I think it'd be better to substitute at the current level.

Copy link
Member Author

Choose a reason for hiding this comment

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

This effectively removes Invariant = true dependencies trimming.

Why?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tested it and the dead branches still get trimmed. Why do you think this removes that?

Also, you can’t substitute this at the higher level because then the Settings class wouldn’t be touched and it’s cctor won’t be run.

And there were concerns in the issue about putting the cctor on GlobalizationMode itself because calling UseNls would force it to run. So splitting the cctor off in a separate class was proposed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, you can’t substitute this at the higher level because then the Settings class wouldn’t be touched and it’s cctor won’t be run.

I think that's what we want for Invariant = true. I think Settings for that mode is redundant.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure how to resolve this comment, plus address all the concerns raised in #49073 (comment). Can you elaborate on what you want here?

Do you want me to split the ILLink.Substitutions.xml apart so Invariant = true and Invariant = false look different? For example:

    <type fullname="System.Globalization.GlobalizationMode">
      <method signature="System.Boolean get_Invariant()" body="stub" value="true" feature="System.Globalization.Invariant" featurevalue="true" />
    </type>
    <type fullname="System.Globalization.GlobalizationMode/Settings">
      <method signature="System.Boolean get_Invariant()" body="stub" value="false" feature="System.Globalization.Invariant" featurevalue="false" />
    </type>

That doesn't seem like an ideal situation IMO.

I don't think your original concern is a problem. Can you explain what are the disadvantages to the current approach I am using?

{
if (TryGetAppLocalIcuSwitchValue(out string? icuSuffixAndVersion))
if (!Invariant)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not a big fan of mixing static ctor with static fields initializers. If you keep the substitution at higher level you could better control when GetInvariantSwitchValue is called

Copy link
Member Author

Choose a reason for hiding this comment

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

What's the concern here? The static field initializers will run at the beginning of the static cctor, just like if you had instance field initializers and a ctor.

- Split the substitutions of GlobalizationMode.Invariant between true and false
- Add a trimming test that ensures Invariant=true trims everything it is supposed to
@eerhardt
Copy link
Member Author

eerhardt commented Jun 7, 2021

@marek-safar - I believe I have addressed your concerns with the latest changes. PTAL.

{
if (TryGetAppLocalIcuSwitchValue(out string? icuSuffixAndVersion))
// These strings can't go into resources, because a resource lookup requires globalization, which requires ICU
if (OperatingSystem.IsBrowser() || OperatingSystem.IsIOS() || OperatingSystem.IsAndroid())
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd go with the simple message everywhere. Otherwise, you would also need to check for tvOS, MacCatalyst, macOS.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll add the check for tvOS and MacCatalyst. My concern with using the "simple" message is that for "desktop" scenarios like Linux and macOS, it would be less informative than it is today.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think macOS users will know what to do with the message and in the case of macOS UI apps it makes even less sense if the user somehow manages to see it.

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe it does make sense for macOS users. We require they have ICU on the machine. We don't bring ICU with .NET on macOS.

See https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu#macos-behavior.

Copy link
Member Author

Choose a reason for hiding this comment

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

@marek-safar - I'm going to merge this for now. If we decide to do something different here for macOS, we can open a new issue/PR for it. But, as-is, this change is keeping the current/existing behavior for macOS.

@eerhardt eerhardt merged commit 3ead4ac into dotnet:main Jun 8, 2021
@eerhardt eerhardt deleted the FixInvariantModeTrimming branch June 8, 2021 22:25
@ghost ghost locked as resolved and limited conversation to collaborators Jul 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
6 participants