Description
I want to open the discussion on consumption of .NET libraries built using C# source gen support https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview .
With every .NET version, more APIs use it and is part of the reason of the unprecedented performance boosts of .NET platform for various computing tasks. A few examples include:
- JSON serialization https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/
- gRPC support ( dotnetconf2022 talk by J.N.King )
- Regex compilation https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-source-generators
- upcoming ideas for aspnetcore apis itself https://github.com/davidfowl/SourceGeneratorPlayground
And I think it is only about time before database libraries or structured loggers (incl. telemetry) will have it as well.
I do not believe that F# needs it's own clone of source generators, there are concepts like type providers or Myriad which allow accomplishing similar goals. Therefore I did not continue this as a comment on fsharp/fslang-suggestions#864 , which I believe has different aspirations.
I do want to reopen the discussion from the .NET library consumption perspective, especially around libraries/frameworks that are massively backed and invested in (like aspnetcore), and are expensive to replicate and part of the big performance wins.
F# is " | Succinct, robust and performant language for .NET" and the ability to consume the fastest of .NET's libraries IMO comes with this motto.
The latest resolution I could find on the topic is "use C# project" fsharp/fslang-suggestions#864 (comment) , which makes sense in the short term (< 3 years) perspective.
However, the broader the usage of C# code gen in well established libraries, the more slices would have to be done in a project to separate the F# pieces (where F# programmers wants to write) and C# parts (simply due to libraries needing that). Important to note that it might spread multiple layers of the application, and therefore isn't just "1 F# and 1C# project", but rather an interleaved sandwich depending on the level of the stack a library is targeting. The cognitive complexity of seeing a project (which turned into a solution by now) like this is objectively bigger and the typical display by Solution Explorer does not make the dependency order visible at a first glance.
Which brings me to the tooling topic - what can we do better in order to support a smooth workflow using such libraries in a project that would want to be F#-only otherwise.
There is an older suggestion about mixed projects fsharp/fslang-suggestions#117 , which was correctly resolved as being a tooling issue and not a change to F# language itself.
My current view is that the user-facing side of this feature could look like embedding a single standalone C# file into middle of a F# project.
That C# file would have access to all project/package dependencies (this is where the source gen stuff is), F# files before it, NOT the files after it ;; and would be only accessible by F# files coming after it.
If this eliminates any worries, I think this would be handy even if always restricted to 1-C#-file scenarios only.
From the IDE side, I could imagine this being a "lightweight project within project", as well as a .cs file being within .fsproj and the F# compiler knowing to split the project into multiple compilation units, invoke Roslyn underneath and putting the results together in the right order.
I will wait for someone more knowledgeable to assess if merging the produced C# & F# ILs together is even a theoretical thought, or it if this would have to be independent .dlls on the output.
This is an XXL item