Fix #9245 by always checking hi-boot for consistency if we find one.
authorEdward Z. Yang <ezyang@cs.stanford.edu>
Sat, 28 Jun 2014 10:56:08 +0000 (11:56 +0100)
committerEdward Z. Yang <ezyang@cs.stanford.edu>
Sat, 28 Jun 2014 15:46:21 +0000 (16:46 +0100)
Summary:
What this fix does is reorder how we look for hi-boot files: we
unconditionally check for an hi-boot file, and if we don't find one, we
check the import graph to see if there was circularity.  This is as
opposed to the previous scheme (check for circularity, then load hi-boot
file).

This costs us an extra file system access every typecheck, which
is not the best.

Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
Test Plan: Validate and check for compiler regressions in nofib

Reviewers: simonpj, austin

Subscribers: simonmar, relrod, carter

Differential Revision: https://phabricator.haskell.org/D30

compiler/iface/TcIface.lhs

index 867674b..14eb723 100644 (file)
@@ -344,26 +344,34 @@ tcHiBootIface hsc_src mod
           else do
 
         -- OK, so we're in one-shot mode.
-        -- In that case, we're read all the direct imports by now,
-        -- so eps_is_boot will record if any of our imports mention us by
-        -- way of hi-boot file
-        { eps <- getEps
-        ; case lookupUFM (eps_is_boot eps) (moduleName mod) of {
-            Nothing -> return emptyModDetails ; -- The typical case
+        -- Re #9245, we always check if there is an hi-boot interface
+        -- to check consistency against, rather than just when we notice
+        -- that an hi-boot is necessary due to a circular import.
+        { read_result <- findAndReadIface
+                                need mod
+                                True    -- Hi-boot file
 
-            Just (_, False) -> failWithTc moduleLoop ;
+        ; case read_result of {
+                Succeeded (iface, _path) -> typecheckIface iface ;
+                Failed err               ->
+
+        -- There was no hi-boot file. But if there is circularity in
+        -- the module graph, there really should have been one.
+        -- Since we've read all the direct imports by now,
+        -- eps_is_boot will record if any of our imports mention the
+        -- current module, which either means a module loop (not
+        -- a SOURCE import) or that our hi-boot file has mysteriously
+        -- disappeared.
+    do  { eps <- getEps
+        ; case lookupUFM (eps_is_boot eps) (moduleName mod) of
+            Nothing -> return emptyModDetails -- The typical case
+
+            Just (_, False) -> failWithTc moduleLoop
                 -- Someone below us imported us!
                 -- This is a loop with no hi-boot in the way
 
-            Just (_mod, True) ->        -- There's a hi-boot interface below us
-
-    do  { read_result <- findAndReadIface
-                                need mod
-                                True    -- Hi-boot file
-
-        ; case read_result of
-                Failed err               -> failWithTc (elaborate err)
-                Succeeded (iface, _path) -> typecheckIface iface
+            Just (_mod, True) -> failWithTc (elaborate err)
+                -- The hi-boot file has mysteriously disappeared.
     }}}}
   where
     need = ptext (sLit "Need the hi-boot interface for") <+> ppr mod