diff options
author | Daniel Gröber <dxld@darkboxed.org> | 2018-12-11 18:36:00 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-12-12 23:25:02 -0500 |
commit | efb6a30f0b70948ba51497bf2831e009ec6e1378 (patch) | |
tree | d39e605b08ddda0c44f8de95ccf9adb65a0af7ae /compiler/iface | |
parent | f0eb404e1b5b296048da3d0b9efe42d5aa9e0f1d (diff) | |
download | haskell-efb6a30f0b70948ba51497bf2831e009ec6e1378.tar.gz |
Fix recompilation checking of pure plugins
Previously when switching from using a Plugin with
`RecompMaybe`/`ForceRecompile` in `pluginRecompile` to a Plugin with
`NoForceRecompile` GHC would never even consider recompiling.
However the previously active plugin could have modified the
compilation output so we should recompile.
Test Plan: validate
Reviewers: bgamari, mpickering
Subscribers: mpickering, rwbarton, carter
GHC Trac Issues: #15858
Differential Revision: https://phabricator.haskell.org/D5299
Diffstat (limited to 'compiler/iface')
-rw-r--r-- | compiler/iface/MkIface.hs | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs index c23f577bba..1ea608e787 100644 --- a/compiler/iface/MkIface.hs +++ b/compiler/iface/MkIface.hs @@ -1325,14 +1325,15 @@ checkVersions hsc_env mod_summary iface -- | Check if any plugins are requesting recompilation checkPlugins :: HscEnv -> ModIface -> IfG RecompileRequired checkPlugins hsc iface = liftIO $ do - -- [(ModuleName, Plugin, [Opts])] + new_fingerprint <- fingerprintPlugins hsc let old_fingerprint = mi_plugin_hash iface - res <- mconcat <$> mapM pluginRecompile' (plugins (hsc_dflags hsc)) - return (pluginRecompileToRecompileRequired old_fingerprint res) + pr <- mconcat <$> mapM pluginRecompile' (plugins (hsc_dflags hsc)) + return $ + pluginRecompileToRecompileRequired old_fingerprint new_fingerprint pr fingerprintPlugins :: HscEnv -> IO Fingerprint fingerprintPlugins hsc_env = do - fingerprintPlugins' $ plugins(hsc_dflags hsc_env) + fingerprintPlugins' $ plugins (hsc_dflags hsc_env) fingerprintPlugins' :: [PluginWithArgs] -> IO Fingerprint fingerprintPlugins' plugins = do @@ -1346,13 +1347,49 @@ fingerprintPlugins' plugins = do (MaybeRecompile fp) -> fp -pluginRecompileToRecompileRequired :: Fingerprint -> PluginRecompile -> RecompileRequired -pluginRecompileToRecompileRequired old_fp pr = - case pr of - NoForceRecompile -> UpToDate - ForceRecompile -> RecompBecause "Plugin forced recompilation" - MaybeRecompile fp -> if fp == old_fp then UpToDate - else RecompBecause "Plugin fingerprint changed" +pluginRecompileToRecompileRequired + :: Fingerprint -> Fingerprint -> PluginRecompile -> RecompileRequired +pluginRecompileToRecompileRequired old_fp new_fp pr + | old_fp == new_fp = + case pr of + NoForceRecompile -> UpToDate + + -- we already checked the fingerprint above so a mismatch is not possible + -- here, remember that: `fingerprint (MaybeRecomp x) == x`. + MaybeRecompile _ -> UpToDate + + -- when we have an impure plugin in the stack we have to unconditionally + -- recompile since it might integrate all sorts of crazy IO results into + -- its compilation output. + ForceRecompile -> RecompBecause "Impure plugin forced recompilation" + + | old_fp `elem` magic_fingerprints || + new_fp `elem` magic_fingerprints + -- The fingerprints do not match either the old or new one is a magic + -- fingerprint. This happens when non-pure plugins are added for the first + -- time or when we go from one recompilation strategy to another: (force -> + -- no-force, maybe-recomp -> no-force, no-force -> maybe-recomp etc.) + -- + -- For example when we go from from ForceRecomp to NoForceRecomp + -- recompilation is triggered since the old impure plugins could have + -- changed the build output which is now back to normal. + = RecompBecause "Plugins changed" + + | otherwise = + let reason = "Plugin fingerprint changed" in + case pr of + -- even though a plugin is forcing recompilation the fingerprint changed + -- which would cause recompilation anyways so we report the fingerprint + -- change instead. + ForceRecompile -> RecompBecause reason + + _ -> RecompBecause reason + + where + magic_fingerprints = + [ fingerprintString "NoForceRecompile" + , fingerprintString "ForceRecompile" + ] -- | Check if an hsig file needs recompilation because its |