Skip to content
This repository has been archived by the owner on Jan 2, 2021. It is now read-only.

Commit

Permalink
Use hie files as source of truth for name source spans.
Browse files Browse the repository at this point in the history
Since we started reusing `.hi` files, this exposes a bug where definitions
aren't available since a bad source span from the `.hi` file gets put into
the NameCache. We rectify by ensuring the span in the NameCache always matches
the one from the `.hie` file.

This has surfaced because an interaction between the commit which uses `.hi`
instead of retypechecking and the change to use the shared global NameCache
to read `.hie` files.
  • Loading branch information
wz1000 committed Jul 14, 2020
1 parent 1919c70 commit 00f35d2
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 26 deletions.
7 changes: 6 additions & 1 deletion src-ghc86/Development/IDE/GHC/HieBin.hs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,12 @@ fromHieName :: NameCache -> HieName -> (NameCache, Name)
fromHieName nc (ExternalName mod occ span) =
let cache = nsNames nc
in case lookupOrigNameCache cache mod occ of
Just name -> (nc, name)
Just name
| nameSrcSpan name == span -> (nc, name)
| otherwise ->
let name' = setNameLoc name span
new_cache = extendNameCache cache mod occ name'
in ( nc{ nsNames = new_cache }, name' )
Nothing ->
let (uniq, us) = takeUniqFromSupply (nsUniqs nc)
name = mkExternalName uniq mod occ span
Expand Down
100 changes: 75 additions & 25 deletions src/Development/IDE/GHC/Compat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,16 @@ module Development.IDE.GHC.Compat(
upNameCache,

module GHC,
#if MIN_GHC_API_VERSION(8,6,0)

#if MIN_GHC_API_VERSION(8,8,0)
module HieTypes,
module HieUtils,
#else
module Development.IDE.GHC.HieTypes,
module Development.IDE.GHC.HieUtils,
#endif

#endif
) where

Expand Down Expand Up @@ -95,36 +102,34 @@ import FastString (FastString)

#if MIN_GHC_API_VERSION(8,6,0)
import Development.IDE.GHC.HieAst (mkHieFile)
import Development.IDE.GHC.HieBin (readHieFile,writeHieFile,NameCacheUpdater(..),HieFileResult(..))
#endif
#if MIN_GHC_API_VERSION(8,10,0)
import HscTypes (mi_mod_hash)
#endif
import Development.IDE.GHC.HieBin

#if MIN_GHC_API_VERSION(8,8,0)
import HscTypes (srcErrorMessages)
import Control.Applicative ((<|>))
import Development.IDE.GHC.HieAst (mkHieFile)
import Development.IDE.GHC.HieBin
import HieUtils
import HieTypes
#else
import Development.IDE.GHC.HieUtils
import Development.IDE.GHC.HieTypes
import System.FilePath ((-<.>))
#endif

#endif

import HieUtils

#else
#if !MIN_GHC_API_VERSION(8,8,0)

import IfaceEnv
#if MIN_GHC_API_VERSION(8,6,0)
import GhcPlugins (srcErrorMessages)
#else
import System.IO.Error
import Development.IDE.GHC.HieTypes
import Development.IDE.GHC.HieUtils
#endif

import Control.Exception (catch)
import IfaceEnv
import Binary
import Data.ByteString (ByteString)
import GhcPlugins (Hsc, srcErrorMessages)
import TcRnTypes
import MkIface
#endif

import Control.Exception (catch)
import System.IO
import Foreign.ForeignPtr

Expand All @@ -136,6 +141,20 @@ hPutStringBuffer hdl (StringBuffer buf len cur)

#endif

#if MIN_GHC_API_VERSION(8,6,0)
supportsHieFiles :: Bool
supportsHieFiles = True

hieExportNames :: HieFile -> [(SrcSpan, Name)]
hieExportNames = nameListFromAvails . hie_exports

#if !MIN_GHC_API_VERSION(8,8,0)
ml_hie_file :: GHC.ModLocation -> FilePath
ml_hie_file ml = ml_hi_file ml -<.> ".hie"
#endif

#endif

upNameCache :: IORef NameCache -> (NameCache -> (NameCache, c)) -> IO c
#if !MIN_GHC_API_VERSION(8,8,0)
upNameCache ref upd_fn
Expand Down Expand Up @@ -275,11 +294,48 @@ nameListFromAvails :: [AvailInfo] -> [(SrcSpan, Name)]
nameListFromAvails as =
map (\n -> (nameSrcSpan n, n)) (concatMap availNames as)

#if !MIN_GHC_API_VERSION(8,8,0)
#if !MIN_GHC_API_VERSION(8,6,0)
-- Reimplementations of functions for HIE files for GHC 8.6

mkHieFile :: ModSummary -> TcGblEnv -> RenamedSource -> ByteString -> Hsc HieFile
mkHieFile ms ts _ _ = return (HieFile (ms_mod ms) es)
where
es = nameListFromAvails (mkIfaceExports (tcg_exports ts))

ml_hie_file :: GHC.ModLocation -> FilePath
ml_hie_file ml = ml_hi_file ml ++ ".hie"

data HieFile = HieFile {hie_module :: Module, hie_exports :: [(SrcSpan, Name)]}

hieExportNames :: HieFile -> [(SrcSpan, Name)]
hieExportNames = hie_exports

instance Binary HieFile where
put_ bh (HieFile m es) = do
put_ bh m
put_ bh es

get bh = do
mod <- get bh
es <- get bh
return (HieFile mod es)

data HieFileResult = HieFileResult { hie_file_result :: HieFile }

writeHieFile :: FilePath -> HieFile -> IO ()
readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult
supportsHieFiles :: Bool

#if MIN_GHC_API_VERSION(8,4,0)

supportsHieFiles = False

writeHieFile _ _ = return ()

readHieFile _ fp = ioError $ mkIOError doesNotExistErrorType "" Nothing (Just fp)

#endif

#endif

getHeaderImports
Expand Down Expand Up @@ -330,11 +386,5 @@ getConArgs = GHC.getConArgs
getConArgs = GHC.getConDetails
#endif

supportsHieFiles :: Bool
supportsHieFiles = True

hieExportNames :: HieFile -> [(SrcSpan, Name)]
hieExportNames = nameListFromAvails . hie_exports

getPackageName :: DynFlags -> Module.InstalledUnitId -> Maybe PackageName
getPackageName dfs i = packageName <$> lookupPackage dfs (Module.DefiniteUnitId (Module.DefUnitId i))

0 comments on commit 00f35d2

Please sign in to comment.