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
Parallel type checking for impl files with backing sig files #13737
Conversation
42dc654
to
cb71bf7
Compare
@nojaf Any idea what actually goes wrong here? |
cb71bf7
to
c20dfd0
Compare
@dsyme for some reason
is no longer recognised. |
@dsyme I can reproduce it with the following: signature: module FSharpPlaygroundProject.InfoReader
type TcGlobals = { A: int }
type ImportMap = { A: int }
type range = { A: int }
type MethInfo = { A: int }
/// An InfoReader is an object to help us read and cache infos.
/// We create one of these for each file we typecheck.
type InfoReader =
new: g: TcGlobals * amap: ImportMap -> InfoReader
static member ExcludeHiddenOfMethInfos:
g: TcGlobals -> amap: ImportMap -> m: range -> minfos: MethInfo list list -> MethInfo list
val ExcludeHiddenOfMethInfos:
g: TcGlobals -> amap: ImportMap -> m: range -> minfos: MethInfo list list -> MethInfo list implementation: module FSharpPlaygroundProject.InfoReader
type TcGlobals = { A: int }
type ImportMap = { A: int }
type range = { A: int }
type MethInfo = { A: int }
/// An InfoReader is an object to help us read and cache infos.
/// We create one of these for each file we typecheck.
type InfoReader(g: TcGlobals, amap: ImportMap) =
static member ExcludeHiddenOfMethInfos
(g: TcGlobals)
(amap: ImportMap)
(m: range)
(minfos: MethInfo list list)
: MethInfo list =
[]
let ExcludeHiddenOfMethInfos (g: TcGlobals) (amap: ImportMap) (m: range) (minfos: MethInfo list list) : MethInfo list =
InfoReader.ExcludeHiddenOfMethInfos g amap m minfos The problem goes away when |
@nojaf I believe the problem is that all the signatures (e.g. of InfoReader.fsi) are present in the tcState at this line https://github.com/dotnet/fsharp/pull/13737/files#diff-efdad7fa53b23cfadc0c316627cd7f8833d0a531db500cc7c220cc4fa0465ab2R1384-R1387 where they shouldn't be. For example, when processing InforReader.fsi only the signatures up to (but not including) InforReader.fsi should be in the tcImplEnv of tcState. I think the tcState and other inputs to use in the delayed parallel work need to be exactly the ones that would have been used here https://github.com/dotnet/fsharp/pull/13737/files#diff-efdad7fa53b23cfadc0c316627cd7f8833d0a531db500cc7c220cc4fa0465ab2R1227 It is probably better to replace these lines with some more explicit return of the delayed stuff to be processed later, including the relevant tcState etc. Plus this entire section](https://github.com/dotnet/fsharp/pull/13737/files#diff-efdad7fa53b23cfadc0c316627cd7f8833d0a531db500cc7c220cc4fa0465ab2R1245-R1290) should likely be factored out as a separate function representing "work to be done to incorporate the results once the check of the impl file is completed". I can pair program a draft with you if you like. |
This is definitely going to be because the signature is present in the name-checking environment when it shouldn't be (the presence of the signature causes multiple InfoReader names to be in scope in a way that's slightly different to the scoping available when starting without the signature present - the latter being what "should" be used for InfoReader.fs). There will be many other manifestations of this problem - e.g. the current diff would allow implementation files to see "later" signature files in the compilation order. Happy to pair-program a better starting point, the current one is just not logically right |
@nojaf we should turn it on by default in the PR for testing purposes |
@nojaf Bootstrap now completes ✔️ I did a quick performance check on my machine after integrating #13740 (comment)
That ignores the time for the Proto phase. Note clean builds hit #13730 so are a PITA until that's fixed. That's looking very promising given that
|
360dfa5
to
2144ba9
Compare
Wonderful news! I'm having similar results when building the Fantomas solution (a couple of projects have signatures, some don't have any) Before: 17.49sec |
I pushed some more fixes regarding diagnostics There's quite a lot of cleanup in this branch now, we could factor it out, though I'm actually happy for the thing to go in as disabled or preview-enabled once green, I'll talk to @vzarytovskii and @KevinRansom about it. Getting exactly the same diagnostics emitted is a bit tricky. The compiler uses this |
@nojaf I could see this causing a bunch of features....
|
Yes, generating all signatures correctly is already on my radar: |
@nojaf The failures now look mostly related to the fact that we delay formatting of diagnostics until "after the whole file has been checked", which means more type inference parameters have been solved. This causes some changes in the types reported in the diagnostics. I need to have a think about the best way to approach this. We use the delay-and-replay-diagnostics in other places but this is the first time we're doing it for anything involving type inference. I guess we need to format the diagnostics early. |
@nojaf I guess people would also love some kind of "store local signature files silently, automatically keep them up to date each time I compile, use them for better compilation performance if they're there, if something changes then update them and re-do compilation" feature. |
1 similar comment
@nojaf I guess people would also love some kind of "store local signature files silently, automatically keep them up to date each time I compile, use them for better compilation performance if they're there, if something changes then update them and re-do compilation" feature. |
@nojaf Determinism failed for the following binaries:
This sort of thing is going to be quite painful to track down :) We will probably need a better binary diff to determine differences in IL metadata (dumping ILDASM and doing a diff may be a good start, but likely even more detail is needed) |
Yeah, I thought about that, but I think you typically will want to generate the signatures once. As soon as the implementation no longer matches the signature you want to |
Would any of this have an impact on the stability of the mvid in references assemblies? |
I imagine that would be geared towards users that don't need or care about signature files (like me), but would like to reap the performance benefits of having them. I mean, why not have the compiler always generate hidden signature files (unless explicit signatures exist) in the bin folder? Sort of like ref assemblies, but on the file level. |
Because it'll break how inferred type changes flow between files. |
Would it be possible to enforce explicit signatures of public APIs in fs files with a compiler flag? A fs file could be treated similar to a signature file then, right? |
This is what I've also had in mind. It could work and would probably be much more pleasant than requiring signature files. @dsyme have you considered that before? |
Couldn't we also invalidate the signature files of all dependent files? |
@auduchinok @kerams @Lenne231 let's take the discussion of compilation and tooling related to signature files to a discussion thread or similar.
I'm not sure. Most likely it's non-determinism in generation of compiler-generated names of some kind. |
@nojaf I think I've fixed the remaining errors. The core of the fix is to do eager formatting on diagnostics as they are produced in the parallel type checking. There's another set of code simplifications in the latest commits:
|
Co-authored-by: Petr Pokorny <petr@innit.cz>
4fa274b
to
e1cbfdc
Compare
Hello @vzarytovskii and @dsyme, any thoughts on how we can move forward with this? |
Many thanks @vzarytovskii for merging this in! |
Congrats @nojaf for your work on this! Congrats to the F# team on getting this in! |
Trying to pick up where #11152 left.