summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZubin Duggal <zubin.duggal@gmail.com>2021-05-18 17:59:50 +0530
committerAdam Sandberg Ericsson <adam@sandbergericsson.se>2021-06-19 17:50:29 +0100
commit7927a1cbb5a52a054cb510e8e3c4e11c198d3917 (patch)
tree8e4179adb2c40587891e842181f4e13316c776fe
parentf6de370c98e647f39eae277217ccf1627553558a (diff)
downloadhaskell-wip/adamse/19744-9.2-backport.tar.gz
Make tcIfaceCompleteMatch lazier.wip/adamse/19744-9.2-backport
Insufficient lazyness causes a loop while typechecking COMPLETE pragmas from interfaces (#19744). (cherry picked from commit 6ce8e68753da41a444021e84405c153eb3d70a67)
-rw-r--r--compiler/GHC/IfaceToCore.hs15
-rw-r--r--testsuite/tests/driver/T19744/Client.hs7
-rw-r--r--testsuite/tests/driver/T19744/Makefile8
-rw-r--r--testsuite/tests/driver/T19744/Mod.hs8
-rw-r--r--testsuite/tests/driver/T19744/T19744.stdout2
-rw-r--r--testsuite/tests/driver/T19744/all.T2
6 files changed, 40 insertions, 2 deletions
diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs
index ee604d8436..fdcdb10a5b 100644
--- a/compiler/GHC/IfaceToCore.hs
+++ b/compiler/GHC/IfaceToCore.hs
@@ -1283,13 +1283,24 @@ tcIfaceCompleteMatches :: [IfaceCompleteMatch] -> IfL [CompleteMatch]
tcIfaceCompleteMatches = mapM tcIfaceCompleteMatch
tcIfaceCompleteMatch :: IfaceCompleteMatch -> IfL CompleteMatch
-tcIfaceCompleteMatch (IfaceCompleteMatch ms mtc) = do
- conlikes <- mkUniqDSet <$> mapM (forkM doc . tcIfaceConLike) ms
+tcIfaceCompleteMatch (IfaceCompleteMatch ms mtc) = forkM doc $ do -- See Note [Positioning of forkM]
+ conlikes <- mkUniqDSet <$> mapM tcIfaceConLike ms
mtc' <- traverse tcIfaceTyCon mtc
return (CompleteMatch conlikes mtc')
where
doc = text "COMPLETE sig" <+> ppr ms
+{- Note [Positioning of forkM]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We need to be lazy when type checking the interface, since these functions are
+called when the interface itself is being loaded, which means it is not in the
+PIT yet. If we are not lazy enough, in certain cases we might recursively try to
+load the same interface in an infinite loop.
+
+For this reason, the forkM should be around as much of the computation as
+possible.
+-}
+
{-
************************************************************************
* *
diff --git a/testsuite/tests/driver/T19744/Client.hs b/testsuite/tests/driver/T19744/Client.hs
new file mode 100644
index 0000000000..4c291f6221
--- /dev/null
+++ b/testsuite/tests/driver/T19744/Client.hs
@@ -0,0 +1,7 @@
+{-# OPTIONS_GHC -Wincomplete-patterns #-}
+module Client where
+
+import Mod
+
+f :: T -> T
+f D = D
diff --git a/testsuite/tests/driver/T19744/Makefile b/testsuite/tests/driver/T19744/Makefile
new file mode 100644
index 0000000000..58917564e3
--- /dev/null
+++ b/testsuite/tests/driver/T19744/Makefile
@@ -0,0 +1,8 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+T19744:
+ '$(TEST_HC)' Mod.hs
+ '$(TEST_HC)' Client.hs
+
diff --git a/testsuite/tests/driver/T19744/Mod.hs b/testsuite/tests/driver/T19744/Mod.hs
new file mode 100644
index 0000000000..f40a9c6fb4
--- /dev/null
+++ b/testsuite/tests/driver/T19744/Mod.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE PatternSynonyms #-}
+module Mod where
+
+data T = C
+
+pattern D = C
+
+{-# COMPLETE D :: T #-}
diff --git a/testsuite/tests/driver/T19744/T19744.stdout b/testsuite/tests/driver/T19744/T19744.stdout
new file mode 100644
index 0000000000..80cc624f31
--- /dev/null
+++ b/testsuite/tests/driver/T19744/T19744.stdout
@@ -0,0 +1,2 @@
+[1 of 1] Compiling Mod ( Mod.hs, Mod.o )
+[2 of 2] Compiling Client ( Client.hs, Client.o )
diff --git a/testsuite/tests/driver/T19744/all.T b/testsuite/tests/driver/T19744/all.T
new file mode 100644
index 0000000000..ccc410dfc2
--- /dev/null
+++ b/testsuite/tests/driver/T19744/all.T
@@ -0,0 +1,2 @@
+srcs = ['Mod.hs', 'Client.hs']
+test('T19744', [run_timeout_multiplier(0.1),extra_files(srcs)], makefile_test, [])