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

Track file versions accurately. #2735

Merged
merged 7 commits into from
Feb 26, 2022
Merged

Track file versions accurately. #2735

merged 7 commits into from
Feb 26, 2022

Conversation

wz1000
Copy link
Collaborator

@wz1000 wz1000 commented Feb 23, 2022

This patch does two things:

  1. It allows us to track the versions of Values which don't come from the VFS, as long as those
    particular Values depended on the GetModificationTime rule
    This is necessary for the recompilation avoidance scheme implemented in Improve recompilation avoidance in the presence of TH #2316

  2. It removes the VFSHandle type and instead relies on snapshots of the VFS state taken on every rebuild
    of the shake session to ensure that we see a consistent VFS state throughout each individual build.

With regards to 2, this is necessary because the lsp library mutates its VFS file store as changes come
in. This can lead to scenarios where the HLS build session can see inconsistent views of the VFS.
One such scenario is.

  1. HLS build starts, with VFS state A
  2. LSP Change notification comes in and lsp updates its internal VFS state to B
  3. HLS build continues, now consulting VFS state B
  4. lsp calls the HLS file change handler, interrupting the build and restarting it.
    However, the build might have completed, or cached results computed using an
    inconsistent VFS state.

This patch does two things:

1. It allows us to track the versions of `Values` which don't come from the VFS, as long as those
   particular `Values` depended on the `GetModificationTime` rule
   This is necessary for the recompilation avoidance scheme implemented in #2316

2. It removes the VFSHandle type and instead relies on snapshots of the VFS state taken on every rebuild
   of the shake session to ensure that we see a consistent VFS state throughout each individual build.

With regards to 2, this is necessary because the lsp library mutates its VFS file store as changes come
in. This can lead to scenarios where the HLS build session can see inconsistent views of the VFS.
One such scenario is.

1. HLS build starts, with VFS state A
2. LSP Change request comes in and lsp updates its internal VFS state to B
3. HLS build continues, now consulting VFS state B
4. lsp calls the HLS file change handler, interrupting the build and restarting it.
   However, the build might have completed, or cached results computed using an
   inconsistent VFS state.
@wz1000 wz1000 added the merge me Label to trigger pull request merge label Feb 26, 2022
@pepeiborra pepeiborra merged commit 905e2ef into master Feb 26, 2022
Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

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

Few comments, some might be worth addressing.

-- time spent checking file modifications (which happens on every change)
-- from > 0.5s to ~0.15s.
-- We might also want to try speeding this up on Windows at some point.
-- TODO leverage DidChangeWatchedFile lsp notifications on clients that
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this TODO in the right place?

@@ -290,10 +290,12 @@ pattern GetModificationTime = GetModificationTime_ {missingFileDiagnostics=True}
-- | Get the modification time of a file.
type instance RuleResult GetModificationTime = FileVersion

-- | Either athe mtime from disk or an LSP version
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
-- | Either athe mtime from disk or an LSP version
-- | Either the mtime from disk or an LSP version

@@ -290,10 +290,12 @@ pattern GetModificationTime = GetModificationTime_ {missingFileDiagnostics=True}
-- | Get the modification time of a file.
type instance RuleResult GetModificationTime = FileVersion

-- | Either athe mtime from disk or an LSP version
-- LSP versions always compare as greater than on disk versions
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why? Is that important?

Nothing -> (,Nothing) . T.decodeUtf8 <$> BS.readFile (fromNormalizedFilePath file)
Just vf -> pure (Rope.toText $ _text vf, Just $ _lsp_version vf)
vfsRef <- asks vfs
vfsData <- liftIO $ vfsMap <$> readTVarIO vfsRef
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use the getVirtualFile action? Or not because we're in a Rules?

(bs, (diags, res)) <- actionCatch
(do v <- action; liftIO $ evaluate $ force v) $
\(e :: SomeException) -> do
pure (Nothing, ([ideErrorText file $ T.pack $ show e | not $ isBadDependency e],Nothing))
modTime <- liftIO $ (currentValue . fst =<<) <$> atomicallyNamed "define - read 2" (getValues state GetModificationTime file)

modTime <- case eqT @k @GetModificationTime of
Copy link
Collaborator

Choose a reason for hiding this comment

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

Something clever is happening here, worth a comment.

shared_change = mkDelta changes
actual_version = case _version of
Nothing -> error "Nothing version from server" -- This is a violation of the spec
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems to be a bug in lsp, please make an issue.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, or maybe we're using the same type to cover OptionalVersionedTextDocumentIdentifier also. I think you can get a missing version here, in fact.

@@ -156,6 +155,8 @@ createExportsMapTc modIface = do
nonInternalModules :: ModuleName -> Bool
nonInternalModules = not . (".Internal" `isSuffixOf`) . moduleNameString

type WithHieDb = forall a. (HieDb -> IO a) -> IO a
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change? now it's duplicated?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge me Label to trigger pull request merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants