summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2014-12-13 22:47:01 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2014-12-15 10:06:55 +0000
commitfbb42b2ea42b6467135f26db47d9c296e7ad75a3 (patch)
tree1caff6c78d38545b8692176b707c049a34cd36e3 /compiler
parent71105aea894d9c39c35248865907207e169f819d (diff)
downloadhaskell-fbb42b2ea42b6467135f26db47d9c296e7ad75a3.tar.gz
Pattern-synonym matcher and builder Ids must be *LocalIds*
This easy-to-make mistake meant that pattern-synonym matcher and builder Ids weren't being treated as locally defined by the simpplier. That meant that we never looked up them up in the environment, got an out-of-date unfolding, which made the Simplifier fall into an infinite loop. This was the cause of Trac #98587, but it was quite tricky to find! In a separate patch I'll make Lint check for locally-bound GlobalIds, since they are always an error.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/basicTypes/Id.hs5
-rw-r--r--compiler/typecheck/TcPatSyn.hs7
2 files changed, 9 insertions, 3 deletions
diff --git a/compiler/basicTypes/Id.hs b/compiler/basicTypes/Id.hs
index fa34a4fd78..ccd6c9b494 100644
--- a/compiler/basicTypes/Id.hs
+++ b/compiler/basicTypes/Id.hs
@@ -314,6 +314,7 @@ We use mkExportedLocalId for things like
- Dictionary functions (DFunId)
- Wrapper and matcher Ids for pattern synonyms
- Default methods for classes
+ - Pattern-synonym matcher and builder Ids
- etc
They marked as "exported" in the sense that they should be kept alive
@@ -329,7 +330,9 @@ of reasons:
dependency analysis (e.g. CoreFVs.exprFreeVars).
* Look them up in the current substitution when we come across
- occurrences of them (in Subst.lookupIdSubst)
+ occurrences of them (in Subst.lookupIdSubst). Lacking this we
+ can get an out-of-date unfolding, which can in turn make the
+ simplifier go into an infinite loop (Trac #9857)
* Ensure that for dfuns that the specialiser does not float dict uses
above their defns, which would prevent good simplifications happening.
diff --git a/compiler/typecheck/TcPatSyn.hs b/compiler/typecheck/TcPatSyn.hs
index 9cc49111ac..65339818fe 100644
--- a/compiler/typecheck/TcPatSyn.hs
+++ b/compiler/typecheck/TcPatSyn.hs
@@ -26,6 +26,7 @@ import Outputable
import FastString
import Var
import Id
+import IdInfo( IdDetails(..) )
import TcBinds
import BasicTypes
import TcSimplify
@@ -254,7 +255,8 @@ tcPatSynMatcher (L loc name) lpat
; let matcher_tau = mkFunTys [pat_ty, cont_ty, fail_ty] res_ty
matcher_sigma = mkSigmaTy (res_tv:univ_tvs) req_theta matcher_tau
- matcher_id = mkVanillaGlobal matcher_name matcher_sigma
+ matcher_id = mkExportedLocalId VanillaId matcher_name matcher_sigma
+ -- See Note [Exported LocalIds] in Id
cont_dicts = map nlHsVar prov_dicts
cont' = mkLHsWrap (mkWpLet prov_ev_binds) $
@@ -326,7 +328,8 @@ mkPatSynBuilderId dir (L _ name) qtvs theta arg_tys pat_ty
| otherwise
= do { builder_name <- newImplicitBinder name mkDataConWorkerOcc
; let builder_sigma = mkSigmaTy qtvs theta (mkFunTys builder_arg_tys pat_ty)
- builder_id = mkVanillaGlobal builder_name builder_sigma
+ builder_id = mkExportedLocalId VanillaId builder_name builder_sigma
+ -- See Note [Exported LocalIds] in Id
; return (Just (builder_id, need_dummy_arg)) }
where
builder_arg_tys | need_dummy_arg = [voidPrimTy]