You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
C# is getting Hot Reload for .NET 6. Will F# receive the same experience? Roslyn has had work done to support this. The F# compiler doesn't seem to have any equivalent work on this.
Describe the solution you'd like
F# can use hot reload just like C#.
Describe alternatives you've considered
Staying behind in terms of tooling again.
Additional context
If the issue is about:
improving a compiler error message: No.
improving/adjusting the parser: No.
Add any other context or screenshots about the feature request here. dotnet/core#5510
It'll happen eventually here, but hot reload is a very new technology that is likely to undergo several changes well after .NET 6. We'll plug into it when it's more stable.
Reacted by Vlad Zarytovskii, Hadrian Tang, dharmaturtle, dhzdhd, Reilly Wood, Piotr Justyna, Lyndon Gingerich and Bent Tranberg
@happypig, @charlesroddie --
what do you want hot reload to do for you? Just asking for a feature name is probably not going to get anything moving. We don't have plenty of other C# features also, and we don't plan on going down the VB route of moaning whenever we don't get some new C# feature.
For me personally the biggest win is with projects that we start with
"dotnet watch run". Usually those are expecto tests or asp.net core
servers. If dotnet watch run would work like fable and keep a compiler in
memory that only recompiles the stuff that is dependent on the files that I
touched, then the dev cycle could speed up dramatically.
I don't think we would need hot module replacement like webpack does - just
restart the process like dotnet watch run would do right now.
Kevin Ransom (msft) ***@***.***> schrieb am Di., 8. Juni
2021, 23:46:
Reacted by Hadrian Tang, Spencer Farley, binwen, pim, Tobias Burger, Piotr Justyna, Bogdan Babiy, Colin Gravill, Diego Freijo, Jannik Buschke and 1 more
Reacted by Spencer Farley, binwen, Piotr Justyna, Bogdan Babiy and Jannik Buschke
dotnet/core#5510 (comment) How fast developers can make code changes and see the resulting impact in their apps is directly proportional to how productive they can be.
Most important is a quick development loop when changing bits of UI (likely to be MAUI with WinUI as primary development platform). For non-UI code I don't need to run code very often, sometimes only once after finishing a work item to check that it works. But for UI code a lot of tweaks and adjustments are important and need to be visualized by running the code.
Hot reload would be perfect for this but does look like a very large task for F# to support Edit and Continue which it is based on.
A typical UI tweak doesn't affect the API of an assembly so reference assemblies will speed up the loop.
Hypothetically if it were possible, while running an application, to edit a dependent project, build it, and switch in the dll, it might capture most of the benefit of hot restart. But this may not be possible in dotnet?
Would support for generating files for FSI scripting, like the one provided by the F# Power Pack back in the day, be an alternative in this case? Together with script debugging, of course.
I can do it in VS 2015 with the plugin for something like winforms, for example. It's more clunky than have it done automatically, for sure, but also closer to home.
There is a gotcha with VisualStudio. The build fails because the VS implicitly modifies the project file, but doesn't save it right away
Rebuilds on any change to any .fs file
The running program will show changes, and much faster than the existing dotnet watch. The main issue is that debug artifacts are not updated with this strategy.
A more accurate description is that rebuilding tries to output both dlls and pdbs, but those resources are already in use by the debugger process.
Reacted by binwen, Don Syme, Florian Verdonck, Piotr Justyna, Quentin Calvez, Simen and John Wostenberg
Reacted by binwen, Don Syme, Piotr Justyna and Quentin Calvez
Reacted by dharmaturtle, Hadrian Tang, binwen, Don Syme and Piotr Justyna
From the README, here's what it does more or less:
Creates an F# dll from a very simple template. Uses FSharp.Compiler.Services to compile it to disk.
Loads that assembly into an AssemblyLoadContext
Generates a delta patch for the assembly. This requires manually constructing metadata tables using MetadataBuilder and some hand-written IL.
Use the ApplyUpdate method which is exposed by the runtime to patch the assembly.
Invokes the running DLL with reflection to confirm it's now returning the new value.
This is far less robust than a real implementation of hot reload that can generate IL and metadata differences from two slightly tweaked compilation contexts, but does show that it is possible. This actually doesn't even need to be implemented in dotnet-watch, it could conceivably be a separate tool. I will say that constructing IL and metadata table patches is pretty tricky business.
Reacted by Laurent Payot, Andrii Chebukin, Tomas Grosup, jcoder58, Natalie Perret, Jakub Majocha and Vinícius Gajo
Reacted by kerams, Jannik Buschke, Kevin, Moritz Jörg, Laurent Payot, Andrii Chebukin, Tobias Burger, Natalie Perret, ijklam and Vinícius Gajo
This would be huge for gamedev. I'm currently developing a game in F# + MonoGame and the productivity loss due to lack of hot reload is massive (it's pretty much a necessity in C# gamedev).
EDIT: wait a minute, is this the same thing as Edit and Continue (which has been requested for much longer than 2021)? Or are these separate features?
It involves massive refactoring of the F# compiler, I went aggressive with it. Right now method body editing works (which is, in my opinion, the best initial bang for buck).
Happy to get comments on general direction, that's my messy first attempt and then we can figure out if/how we should be doing things like FSharpWorkspace support, etc.
Reacted by John Wostenberg, Kevin, Jimmy Byrd, Ole Tytlandsvik, CodeConscious and weebs
Should be function bodies too I think, need to test it more, it may depend on how the compiled representation changes. The best way to try it out is currently one with a super limited demo. If you check out that repo, I think you need to build it using build.sh, something like that (I forget exactly what I did to get the dotnet sdk in the ./dotnet folder), and then you can run something like this:
DOTNET_MODIFIABLE_ASSEMBLIES=debug \
./.dotnet/dotnet run --project tests/projects/HotReloadDemo/HotReloadDemoApp/HotReloadDemoApp.fsproj -- --interactive
And then it should give you a file path to a Message.fs file that you can edit, and then hit enter to see it hot-reloaded. So you can test out various things with that if you like. You can't point it at arbitrary F# code yet, I was just using that for validation purposes.
I have been working on it on and off for the last few months...lately it's been "off" as I've been busy with other work that actually pays 😅
More eyeballs on it is always a good thing though.
EDIT: I spoke with @T-Gro about this about six months ago to get some general direction, here's the discussion if anyone may find it of interest. This meeting was shortly after my previous comment in this thread where I got the janky demo version of hot reload working.
EDIT2: Just to give a bit more detail on the direction in that PR (and I don't have too much time to get into it now), first I built the infra for hot reload on System.Reflection.Metadata, and built it mostly outside of the existing "full assembly" code that is contained in ilwrite.fs, ilbinary.fs, etc. Later on, starting around 97a044 I decided to try and unify delta emission and full assembly writing, so that's kind of what comes after that in the commit history. And that's also where it starts to get really REALLY invasive (even though it kind of already was), where I started to unify the types used for full assembly generation with whatever I was doing for the delta generation. Although then I realized that that we're use SRM for PDB writing anyway, so maybe I should've just tried to shift the F# compiler to use that fully? Anyway I got kind of busy so haven't done any work on it in a few weeks.
Invasive changes to bring in S.R.M (reading or writing) were always a risk (I do come around #8081 at least once a year and would want it in as well), and we would need to be extremely careful.
For an experimental feature like this, we could use the fact that it is all contained in a single file, and create a copy sitting next to it.
That way, existing usage would get the old code, and feature implementation could do "whatever it wants" in its copy.
We would then have the ability to switch between them based on feature stability, and later delete on or the other.
Reacted by Jakub Majocha, Jimmy Byrd, Hadrian Tang, Asttear, Igor Bagdamyan, Vinícius Gajo, Spencer Farley, ArmoryNode, Richard Chamorro and Jannik Buschke
Reacted by Tomas Grosup, Spencer Farley, ArmoryNode, weebs, Richard Chamorro and Jannik Buschke
Reacted by Andrii Chebukin, reinux, Kevin, Jimmy Byrd, Bronson Bata, Hadrian Tang, Vinícius Gajo, ijklam, ArmoryNode, Richard Chamorro and 1 more
Been a few months, decided to come back to this. Got a few new PRs, feel free to play around with it.
Foundations - behavior-neutral AbstractIL/ilwrite groundwork: NatElkins#2 Full implementation overview - the whole thing as one diff, with design docs linked in the description: NatElkins#3 Small stacked cleanup on top of that - NatElkins#4
And here's the PR for the SDK side (dotnet-watch integration, multi-project support):
EDIT: I put everything for the fsharp repo in one draft PR over here: #19941
Reacted by Kevin, kerams, Hadrian Tang, Jannik Buschke, Angel D. Munoz, reinux and Andrii Chebukin
Reacted by Jakub Majocha, kerams, Giedrius Bružas, Jimmy Byrd, Hadrian Tang, Jannik Buschke, Andrii Chebukin, Angel D. Munoz, Gauthier Segay, ieviev and 3 more
Reacted by kerams, Sam Smucny, Hadrian Tang, Andrii Chebukin, Angel D. Munoz, ieviev and reinux
Activity
Happypig375 commentedon Jun 5, 2021
https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/
Of course F# is staying behind in terms of tooling again. 😞
charlesroddie commentedon Jun 5, 2021
What's the current status if:
Is hot reload able to support that currently? I.e. loading the updated assembly.
cartermp commentedon Jun 5, 2021
It'll happen eventually here, but hot reload is a very new technology that is likely to undergo several changes well after .NET 6. We'll plug into it when it's more stable.
KevinRansom commentedon Jun 8, 2021
@happypig, @charlesroddie --
what do you want hot reload to do for you? Just asking for a feature name is probably not going to get anything moving. We don't have plenty of other C# features also, and we don't plan on going down the VB route of moaning whenever we don't get some new C# feature.
forki commentedon Jun 9, 2021
charlesroddie commentedon Jun 9, 2021
From the linked thread:
Most important is a quick development loop when changing bits of UI (likely to be MAUI with WinUI as primary development platform). For non-UI code I don't need to run code very often, sometimes only once after finishing a work item to check that it works. But for UI code a lot of tweaks and adjustments are important and need to be visualized by running the code.
Hot reload would be perfect for this but does look like a very large task for F# to support Edit and Continue which it is based on.
A typical UI tweak doesn't affect the API of an assembly so reference assemblies will speed up the loop.
Hypothetically if it were possible, while running an application, to edit a dependent project, build it, and switch in the dll, it might capture most of the benefit of hot restart. But this may not be possible in dotnet?
heronbpv commentedon Jun 9, 2021
Would support for generating files for FSI scripting, like the one provided by the F# Power Pack back in the day, be an alternative in this case? Together with script debugging, of course.
I can do it in VS 2015 with the plugin for something like winforms, for example. It's more clunky than have it done automatically, for sure, but also closer to home.
albertwoo commentedon Jun 24, 2021
I am using blazor with fsharp. Hot reload will speed up the poductivity a lot.
farlee2121 commentedon Jul 20, 2021
This is a critical tooling enhancement for my usage of F#.
Is there some way I can contribute to move up the timeline?
(I don't currently have a great feel for the scope of work needed)
vzarytovskii commentedon Jul 20, 2021
I don't think we have a full understanding of what has to be done yet.
farlee2121 commentedon Aug 23, 2021
I decided to spelunk and get a better idea of what it takes to implement hot reload.
Full notes are in this gist https://gist.github.com/farlee2121/24915fb0518ad4ca6631bc33d0ff401c
Finds so far
Microsoft.CodeAnalysis.ExternalAccess.Watch.Api.WatchHotReloadService.Updatein order to reuse DeltaAppliersMicrosoft.DotNet.Watcher.Tools.HotReload.csbecauseCompilationHandleris tied to RoslynOustanding investigations
farlee2121 commentedon Sep 1, 2021
A quick update. I made an experimental fork.
It's pretty basic so far
The running program will show changes, and much faster than the existing dotnet watch.
The main issue is that debug artifacts are not updated with this strategy.A more accurate description is that rebuilding tries to output both dlls and pdbs, but those resources are already in use by the debugger process.
NatElkins commentedon Sep 2, 2021
@farlee2121 Don't be shy, post a GIF!
farlee2121 commentedon Sep 6, 2021
Here's a demonstration of the most basic scenario, changing a file
39 remaining items
albertwoo commentedon Dec 25, 2024
I know fable is there, but a lot of frameworks are targeting to dotnet.
reinux commentedon Dec 25, 2024
I do very much envy Fable's compile times when I'm working on server side or desktop stuff.
NatElkins commentedon Dec 30, 2024
Here's a recent presentation from JetBrains' .NET Days that goes over some hot reload internals: https://www.youtube.com/watch?v=MGUPW9sK2Vg
NatElkins commentedon Apr 2, 2025
Here's another one with some internal details: https://www.youtube.com/watch?v=tVmABHwxuqE
xperiandri commentedon Apr 3, 2025
Cool! now we know who we need to ping and ask questions
NatElkins commentedon Apr 17, 2025
Just want to say I got a very very minimal and janky version of hot reloading working F#, which you can take a look at here:
https://github.com/NatElkins/hot_reload_poc
From the README, here's what it does more or less:
Creates an F# dll from a very simple template. Uses FSharp.Compiler.Services to compile it to disk.
Loads that assembly into an AssemblyLoadContext
Generates a delta patch for the assembly. This requires manually constructing metadata tables using MetadataBuilder and some hand-written IL.
Use the ApplyUpdate method which is exposed by the runtime to patch the assembly.
Invokes the running DLL with reflection to confirm it's now returning the new value.
This is far less robust than a real implementation of hot reload that can generate IL and metadata differences from two slightly tweaked compilation contexts, but does show that it is possible. This actually doesn't even need to be implemented in
dotnet-watch, it could conceivably be a separate tool. I will say that constructing IL and metadata table patches is pretty tricky business.garrettlondon1 commentedon Jun 18, 2025
+1, Blazor projects depending on F# class libraries would benefit immensely from this
jwosty commentedon Dec 10, 2025
What are the plans for 2026?
This would be huge for gamedev. I'm currently developing a game in F# + MonoGame and the productivity loss due to lack of hot reload is massive (it's pretty much a necessity in C# gamedev).
EDIT: wait a minute, is this the same thing as Edit and Continue (which has been requested for much longer than 2021)? Or are these separate features?
NatElkins commentedon Dec 10, 2025
@jwosty I have a branch here that works: NatElkins#1
It involves massive refactoring of the F# compiler, I went aggressive with it. Right now method body editing works (which is, in my opinion, the best initial bang for buck).
Happy to get comments on general direction, that's my messy first attempt and then we can figure out if/how we should be doing things like FSharpWorkspace support, etc.
jwosty commentedon Dec 10, 2025
@NatElkins incredible - I will have to give that a try. Is it just method bodies, or function bodies too? I could absolutely live with only those two.
reinux commentedon Dec 10, 2025
Nice, this would be great for web dev with server-side rendering as well.
NatElkins commentedon Dec 10, 2025
Should be function bodies too I think, need to test it more, it may depend on how the compiled representation changes. The best way to try it out is currently one with a super limited demo. If you check out that repo, I think you need to build it using
build.sh, something like that (I forget exactly what I did to get the dotnet sdk in the./dotnetfolder), and then you can run something like this:And then it should give you a file path to a
Message.fsfile that you can edit, and then hit enter to see it hot-reloaded. So you can test out various things with that if you like. You can't point it at arbitrary F# code yet, I was just using that for validation purposes.I have been working on it on and off for the last few months...lately it's been "off" as I've been busy with other work that actually pays 😅
More eyeballs on it is always a good thing though.
EDIT: I spoke with @T-Gro about this about six months ago to get some general direction, here's the discussion if anyone may find it of interest. This meeting was shortly after my previous comment in this thread where I got the janky demo version of hot reload working.
EDIT2: Just to give a bit more detail on the direction in that PR (and I don't have too much time to get into it now), first I built the infra for hot reload on System.Reflection.Metadata, and built it mostly outside of the existing "full assembly" code that is contained in ilwrite.fs, ilbinary.fs, etc. Later on, starting around 97a044 I decided to try and unify delta emission and full assembly writing, so that's kind of what comes after that in the commit history. And that's also where it starts to get really REALLY invasive (even though it kind of already was), where I started to unify the types used for full assembly generation with whatever I was doing for the delta generation. Although then I realized that that we're use SRM for PDB writing anyway, so maybe I should've just tried to shift the F# compiler to use that fully? Anyway I got kind of busy so haven't done any work on it in a few weeks.
T-Gro commentedon Dec 11, 2025
Invasive changes to bring in S.R.M (reading or writing) were always a risk (I do come around #8081 at least once a year and would want it in as well), and we would need to be extremely careful.
For an experimental feature like this, we could use the fact that it is all contained in a single file, and create a copy sitting next to it.
That way, existing usage would get the old code, and feature implementation could do "whatever it wants" in its copy.
We would then have the ability to switch between them based on feature stability, and later delete on or the other.
NatElkins commentedon Feb 12, 2026
It ain't pretty, but it works!
NatElkins#1
Screen.Recording.2026-02-12.at.2.27.52.PM.mov
NatElkins commentedon Jun 12, 2026
Been a few months, decided to come back to this. Got a few new PRs, feel free to play around with it.
Foundations - behavior-neutral AbstractIL/ilwrite groundwork: NatElkins#2
Full implementation overview - the whole thing as one diff, with design docs linked in the description: NatElkins#3
Small stacked cleanup on top of that - NatElkins#4
And here's the PR for the SDK side (dotnet-watch integration, multi-project support):
NatElkins/sdk#1
If you want to actually see it run, there's a copy-paste quickstart that goes from two clones to live-editing a running app (including adding lambdas, which now hot-patch in place): https://github.com/NatElkins/fsharp/blob/hot-reload-v2/docs/hot-reload-quickstart.md
EDIT: I put everything for the
fsharprepo in one draft PR over here: #19941