-
Notifications
You must be signed in to change notification settings - Fork 1
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
Missing reference in Transparent Compiler #1
base: experiments
Are you sure you want to change the base?
Missing reference in Transparent Compiler #1
Conversation
I do think that the IDE should still require all preceding files to be typechecked for most purposes. It should avoid lots of issues like the one described in this PR. |
You are most likely correct, although I would like to hear some specifics to move beyond gut feelings. I want to keep an open mind as dotnet#15179 currently produces a green build. So I guess, either VS tests don't cover this, or it either just works for them by checking only the dependent files. |
This is a great point. We should see if there are other issues like this. If it was just this, then I can imagine even giving up on this feature if it makes everything faster for a particular project (maybe it would be configurable). Also what might be a way is to deliver the typechecking results for current file as fast as we can and then start checking everything else in the background. So you could already work with a type checked file and the code fix would appear once available. Which I think we want to do anyway, so you can see diagnostics for the entire solution, which can change as you edit (though probably this needs to be configurable as well for if someone wants to save their laptop battery). And this way we wouldn't need to come up with any extra magic from untyped tree.
Most likely there aren't any tests for this. Or if there are they're not using Transparent Compiler - that PR doesn't replace current BackgroundCompiler with it, it just adds it as an opt-in feature. I'll need to go through the tests and plug it in where possible. |
This is definitely the case in AdaptiveLSP of FSAC. When we call to typecheck a file, we rely on the caching in the compiler and calls to |
@nojaf Thanks for finding this case! It shows quite a serious/interesting issue for the tooling to think about.
Yes, it's correct, features do indeed rely on type checking of the previous files. We can redesign some features or use heuristics, but the main issue may be editing code in general and unexpected slow downs in features. Consider this code: module Module
let f x = x Typing From the top of my head, what we could try to do for the compiler service is something this: require the intermediates file type checking the first time, and allow using old results when changes wouldn't normally be seen by the analyzed file:
First time File4.fs is analyzed, all previous files check results would be required. If there's a change to File1.fs, we can skip File3.fs analysis when analyzing File4.fs again and use its previous check results. I'm not sure how feasible this is going to be, but it could be an interesting compromise that would in theory still allow skipping many files and would allow providing the same features quality. Another approach we could try is adding a flag to |
I think there's another unrelated but important issue here: cross-project analysis. One of the important scenarios I have in mind is editing a library code then jumping to a place that uses this library in another project (e.g. tests or app code). We would really want to skip the intermediate files here too, but (unless something is changed in this branch already) it would first check all the files in the library project, serializing the F# metadata along the way, then deserialize it all back when importing into the other project. Due to how the projects are isolated, we just can't use graph at all, even if me make it work for the editor features. What we could also try to do while replacing |
It wouldn't provide the same features quality, right? It wouldn't work for code completion and quick fixes, as you explained later. I do want to stress that "slow type checking" is not necessarily slow.
graph checking of all the files should be as fast as just checking X's dependency graph. Of course, avoiding unnecessary work is always better. Somewhat-related: Personally I think the following IDE feature would be useful: I do like @auduchinok 's suggestion to avoid unnecessary (de)serialization of TC information.
Essentially, the current project isolation can be thought of as adding virtual "project" nodes in the dependency graph. |
For some features we only need faster symbols lookup in unopened files, and it'd be OK if intermediate files aren't checked. It seems it could make a significant difference in some cases. |
@0101 : How would it play with the "unopened documents" live analysis we want to have anyway? What if the file in API argument and its direct dependencies would be type-checked as you have in your WIP PR right now, but the rest - instead of ignoring it - would be processed afterwards in a background operation if they got stale ? The obvious cost is increased complexity for cancellation and scheduling between active and background requests. |
That was my suggestion in a post above. I don't think there would be much extra complexity if the caching system works properly. Maybe just detecting which checking requests should be canceled - but we will probably need to do that anyway if the IDEs don't handle it. However, @safesparrow has a good point that this will deliver the results you might potentially need slower than forcing to check all files above the requested file, because much of it (if not all of it) could be done in parallel to the required dependencies. Maybe we could have a more sophisticated graph processing algorithm with high priority nodes (requested file and its dependencies) and low priority nodes (other files above, maybe even below?), where low priority ones would be started as soon as they're unblocked, but we wouldn't wait for them to return the result. Not sure if it's feasible, or even worth it for how much better experience it would deliver. Would be nice to have more insight into common F# project dependency graphs. |
I think this is very desirable. I often wish FCS would at the same time:
AFAIK there is no system currently that allows for this. Such a system should allow the user to dedicate a certain amount of resources (no. of threads) to certain tasks (main/background). Once such a system is in place, the perfect solution would be as you describe - type-check file dependencies immediately, and schedule type-checking of remaining files in the background. |
Another thing to consider when talking about cross-project references is dotnet#15180. If we are able to work with TAST symbols directly, then there's another possible way to fix this issue. Which would be good, as it breaks the cross-project analysis considerably. |
Hi all,
I played around this morning with the 'Transparent Compiler' and I really like where this is going!
Praise aside, I found an interesting scenario I wish to discuss.
When
checker.ParseAndCheckFileInProject
is called, the Transparent Compiler will type-check the file and all the dependencies. This works out nicely but gets into a grey area when you start to edit the code where you are no longer in a valid state.Please first read
tests/FSharp.Compiler.Service.Tests/TransparentTests.fs
!My question is about how the different editors will deal with this kind of code fix:

As mentioned in the unit test, the editor might rely on the fact that all files are type-checked (as is the case in the present-day situation), while currently, in the Transparent Compiler (at the time of writing), this is not the case.
Some questions to ponder over:
checker.ParseAndCheckFileInProject
is called, should each file up to the requested file be type-checked or are we happy with the more performant-only type-check the dependent files?Internally in
DependencyResolution.mkGraph
we construct aTrie
with more or less the information we are after. typeX
in the unit test can easily be pinpointed toProject.A
after we processed all the AST. We don't exactly have this today, but I can see it is quite feasible to capture.Tagging a bunch of people: @auduchinok, @DedSec256, @0101, @psfinaki, @baronfel, @TheAngryByrd, @safesparrow, @dawedawe. Please tag others if I missed anyone.
Let us know what the implications would be right now for the editor you work on.
PS: There are no intentions to merge this PR. It only exists to kick off the conversation.