Skip to content
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

[WIP] Serialization and deserialization of the typechecking data #18162

Draft
wants to merge 3 commits into
base: feature/reuse-typechecking-results
Choose a base branch
from

Conversation

psfinaki
Copy link
Member

Wonder if this even counts as a prototype? But at least some steps towards that direction :)

This will be needed for the Stage 2 of the reuse typechecking results feature, as per the design doc here.

See the comments in code and in the PR.

Copy link
Contributor

❗ Release notes required

@psfinaki,

Caution

No release notes found for the changed paths (see table below).

Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on Keep A Changelog format.

The following format is recommended for this repository:

* <Informative description>. ([PR #XXXXX](https://github.com/dotnet/fsharp/pull/XXXXX))

See examples in the files, listed in the table below or in th full documentation at https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html.

If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

You can open this PR in browser to add release notes: open in github.dev

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/9.0.200.md No release notes found or release notes format is not correct



[<Fact>]
let PickleAndUnpickleTcData() =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More generally, how to test this?

Comparing the original and restored TC information is hard currently since many types don't have equality allowed. Should we change this just for the purpose of testing? Doesn't feel right.

What else - create baselines for resources (bytes)?

Rely on the higher-level testing?

Hope & pray? (like we do with other pickling & unpickling stuff...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E2e testing of an integrated scenario.

Which can then compare e.g. IL baseline and separately compare debug info data, their equality is easier tested. Also, those should not be deviating anyway.

The same way pickling and unpickling is tested - it is not tested by hope & pray, it is tested by integration tests using referenced pickled version of F# code, such as the code in FSharp.Core and its signature and optimization data. (e.g. integration tests proving that Fsharp.Core calls are being correctly inlined thanks to optimization data)


()

tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile
Copy link
Member Author

@psfinaki psfinaki Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So out of 4 things, tcState and tcEnvAtEndOfLastFile will be cumbersome (yet likely possible) for pickling/unpickling - it's a lot of information we haven't dealt with. Wonder if this can be somehow worked around?

@@ -901,17 +949,17 @@ type TcAssemblyResolutions(tcConfig: TcConfig, results: AssemblyResolution list,

for UnresolvedAssemblyReference (referenceText, _ranges) in unresolved do
if referenceText.Contains("mscorlib") then
Debug.Assert(false, sprintf "whoops, did not resolve mscorlib: '%s'%s" referenceText addedText)
//Debug.Assert(false, sprintf "whoops, did not resolve mscorlib: '%s'%s" referenceText addedText)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason this breaks some test mockery, didn't investigate yet.

@@ -5899,6 +5899,12 @@ type PickledCcuInfo =

override _.ToString() = "PickledCcuInfo(...)"

type PickledTcInfo = {
MainMethodAttrs: Attribs
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't use TopAttribs as they are defined later in Checking

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW would a similar problem for things like TcEnv or TcState

p_list p_pragma x st

and p_checked_impl_file (file: CheckedImplFile) st =
p_tup5
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this doesn't pickle all the info yet, see the comment for unpickling.

let WriteTypecheckingData (tcConfig: TcConfig, tcGlobals, fileName, inMem, ccu, tcInfo) =

// need to understand the naming and if we even want two resources here...
let rName = "FSharpTypecheckingData"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 2 resources here?
Typechecking reuse should not be complicated with backwards compat, just support file format of the same compiler version only.

let memA = byteReaderA ()

let memB =
match byteReaderB with
Copy link
Member

@T-Gro T-Gro Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is byteReaderB good for here?
I think it should work without it.

UNLESS it is needed to reuse the most of existing pickling for signatures. Then of course let's have it for the sake of not reimplementing what has been done.

qualifiedNameOfFile,
pragmas,
signature,
// ModuleOrNamespaceContents needs implementing, feels hard but doable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the continuous progress should be happening.
Starting from most common types/expressions to the more rare ones.

isScript,
// this anon record map can be likely easily built in top of primitives here
Unchecked.defaultof<_>,
// something about debug points, not sure we care here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do care to have debugging working in VS, yes :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After all, this whole story is to speed up the inner dev loop, which is happening in DEBUG mode normally.

@@ -0,0 +1,166 @@
module FSharp.Compiler.Service.Tests.TypedTreePickleTests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this as an exploratory tool.

If the build times of the test project make this exploration slower, I believe (?) the same should be doable as an .fsx as well - referencing the compiler and experimenting there.

(just a proposal - this can temporarily live in the test project as well, but maybe adhocly playing with the inner details like here would have a faster feedback loop when in a script file, scratchpad.fsx)

@psfinaki psfinaki changed the base branch from main to feature/reuse-typechecking-results December 19, 2024 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: New
Development

Successfully merging this pull request may close these issues.

2 participants