Skip to content

Fix type forwarding for init/record workaround #895

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

Merged
merged 4 commits into from
Dec 2, 2022

Conversation

andyleejordan
Copy link
Contributor

@andyleejordan andyleejordan commented Nov 8, 2022

This PR fixes the magic around the IsExternalInit field that allowed OmniSharp to opt-in to the use of init and record semantics before they were available normally. This prior workaround, however, now can easily cause problems after updating to .NET 6.0, where the field is available. The primary problem manifests with a net6.0 app consumes the OmniSharp library (targeting netstandard2.0) and attempts to use any of the record structs (with init fields), such as PowerShell Editor Services' test suite when creating CompletionRecord structs. The type resolution would fail on initialization of the struct because the set method was not pointing to the right place, similar to what happened to System.Text.Json (which also opted in early with that workaround) in dotnet/runtime#61737.

.NET may eventually find a solution (see dotnet/sdk#23319) that is more elegant than this, but for now the correct thing to do, as confirmed with @ericstj, is as seen in this PR: forward the type when targeting .NET 5.0 or greater, and otherwise define it internally (it should never be defined publicly). Then in consuming libraries, if they similarly used the same IsExternalInit code, the same correction should be applied (as was done to PowerShell Editor Services in PowerShell/PowerShellEditorServices#1953).

I also updated the test apps and sample program just to target net6.0 instead of netcoreapp3.1 for simplicity (note the prior targets had redundant frameworks, probably from a prior find/replace). This will not affect consumers.

Finally, I fixed the macOS CI build by updating the build tool that was failing to install, and then re-enabled CI.

@andyleejordan
Copy link
Contributor Author

andyleejordan commented Nov 8, 2022

It is working on macOS 🥳:

═══════════════════════════════════════════════════════════
Target                                 Status      Duration
───────────────────────────────────────────────────────────
Clean                                  Succeeded     < 1sec
DotnetToolRestore                      Succeeded     < 1sec
Restore                                Succeeded       0:04
Build                                  Succeeded       2:53
Test                                   Succeeded       1:45
GenerateCodeCoverageReportCobertura    Succeeded       0:09
GenerateCodeCoverageBadges             Succeeded       0:03
GenerateCodeCoverageSummary            Succeeded       0:03
GenerateCodeCoverageReport             Succeeded       0:10
Pack                                   Succeeded       0:05
───────────────────────────────────────────────────────────
Total                                                  5:17
═══════════════════════════════════════════════════════════

Build succeeded on 11/8/2022 1:58:02 PM. \(^ᴗ^)/
@andys-mac-mini .../csharp-language-server-protocol andschwa/fix-records ≡

@codecov
Copy link

codecov bot commented Nov 8, 2022

Codecov Report

❗ No coverage uploaded for pull request base (master@cd10e33). Click here to learn what that means.
The diff coverage is n/a.

@@            Coverage Diff            @@
##             master     #895   +/-   ##
=========================================
  Coverage          ?   72.32%           
=========================================
  Files             ?      255           
  Lines             ?    12847           
  Branches          ?      817           
=========================================
  Hits              ?     9292           
  Misses            ?     3555           
  Partials          ?        0           

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@andyleejordan
Copy link
Contributor Author

andyleejordan commented Nov 9, 2022

This was confusing as all get out, and I'm still not sure I understand exactly what breaks and why, but I know how to fix it 🤷

@ericstj
Copy link

ericstj commented Nov 15, 2022

.NET may eventually find a solution (see dotnet/sdk#23319) that is more elegant than this

That issue is just about flagging this compatibility problem at build time for libraries that have it. Right now the problem is still a library issue. Libraries defined IsExternalInit locally and that "leaks" to their callers in public API. If they want to remain compatible with that public API they need to keep defining the type locally, or forward the local definition to the framework version. The only "more elegant fix" would be a hack to have the runitme's type loader ignore the assembly difference here and effectively "inject" a type forward. I don't expect the runtime will ever do that, and likely not retroactively on net5.0 - net7.0, so this fix is the right one regardless. cc @jkotas @jaredpar

@jkotas
Copy link

jkotas commented Nov 15, 2022

I agree with @ericstj assessment. This is one of the dangers of using new C# features on old runtimes.

@andyleejordan
Copy link
Contributor Author

Thanks for the explanation (and all your help) @ericstj and @jkotas!

@david-driscoll david-driscoll merged commit aac9b59 into OmniSharp:master Dec 2, 2022
@github-actions github-actions bot added this to the v0.19.7 milestone Dec 2, 2022
@github-actions github-actions bot added the mysterious We forgot to label this label Dec 2, 2022
@andyleejordan andyleejordan deleted the andschwa/fix-records branch December 2, 2022 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mysterious We forgot to label this
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants