summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2014-06-24 13:24:36 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2014-06-24 13:24:52 +0100
commit0757831eaca96c8ebfd99fc51427560d3568cffa (patch)
tree10915507b1b7e07fdc9de8b9a1d6dab40d8deb2f
parent8a0aa198f78cac1ca8d0695bd711778e8ad086aa (diff)
downloadhaskell-0757831eaca96c8ebfd99fc51427560d3568cffa.tar.gz
Add Note [Placeholder PatSyn kinds] in TcBinds
This is just documentation for the fix to Trac #9161
-rw-r--r--compiler/typecheck/TcBinds.lhs44
-rw-r--r--compiler/typecheck/TcEnv.lhs3
2 files changed, 36 insertions, 11 deletions
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index 273ef82c34..887e41c0d5 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -274,6 +274,30 @@ time by defaulting. No no no.
However [Oct 10] this is all handled automatically by the
untouchable-range idea.
+Note [Placeholder PatSyn kinds]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider this (Trac #9161)
+
+ {-# LANGUAGE PatternSynonyms, DataKinds #-}
+ pattern A = ()
+ b :: A
+ b = undefined
+
+Here, the type signature for b mentions A. But A is a pattern
+synonym, which is typechecked (for very good reasons; a view pattern
+in the RHS may mention a value binding) as part of a group of
+bindings. It is entirely resonable to reject this, but to do so
+we need A to be in the kind environment when kind-checking the signature for B.
+
+Hence the tcExtendKindEnv2 patsyn_placeholder_kinds, which adds a binding
+ A -> AGlobal (AConLike (PatSynCon _|_))
+to the environment. Then TcHsType.tcTyVar will find A in the kind environment,
+and will give a 'wrongThingErr' as a result. But the lookup of A won't fail.
+
+The _|_ (= panic "fakePatSynCon") works because the wrongThingErr call, in
+tcTyVar, doesn't look inside the TcTyThing.
+
+
\begin{code}
tcValBinds :: TopLevelFlag
-> [(RecFlag, LHsBinds Name)] -> [LSig Name]
@@ -281,12 +305,9 @@ tcValBinds :: TopLevelFlag
-> TcM ([(RecFlag, LHsBinds TcId)], thing)
tcValBinds top_lvl binds sigs thing_inside
- = do { -- Add fake entries for pattern synonyms so that
- -- precise error messages can be generated when
- -- trying to use a pattern synonym as a kind
- traceTc "Fake lifted patsyns:" (vcat (map ppr patsyns))
- -- Typecheck the signature
- ; (poly_ids, sig_fn) <- tcExtendKindEnv2 [(patsyn, fakePatSynCon) | patsyn <- patsyns] $
+ = do { -- Typecheck the signature
+ ; (poly_ids, sig_fn) <- tcExtendKindEnv2 patsyn_placeholder_kinds $
+ -- See Note [Placeholder PatSyn kinds]
tcTySigs sigs
; let prag_fn = mkPragFun sigs (foldr (unionBags . snd) emptyBag binds)
@@ -298,11 +319,12 @@ tcValBinds top_lvl binds sigs thing_inside
tcBindGroups top_lvl sig_fn prag_fn
binds thing_inside }
where
- patsyns = [ name
- | (_, lbinds) <- binds
- , L _ (PatSynBind{ patsyn_id = L _ name }) <- bagToList lbinds
- ]
- fakePatSynCon = AGlobal $ AConLike $ PatSynCon $ panic "fakePatSynCon"
+ patsyn_placeholder_kinds -- See Note [Placeholder PatSyn kinds]
+ = [ (name, placeholder_patsyn_tything)
+ | (_, lbinds) <- binds
+ , L _ (PatSynBind{ patsyn_id = L _ name }) <- bagToList lbinds ]
+ placeholder_patsyn_tything
+ = AGlobal $ AConLike $ PatSynCon $ panic "fakePatSynCon"
------------------------
tcBindGroups :: TopLevelFlag -> TcSigFun -> PragFun
diff --git a/compiler/typecheck/TcEnv.lhs b/compiler/typecheck/TcEnv.lhs
index 28cd7a61d4..be2058f354 100644
--- a/compiler/typecheck/TcEnv.lhs
+++ b/compiler/typecheck/TcEnv.lhs
@@ -874,6 +874,9 @@ notFound name
}
wrongThingErr :: String -> TcTyThing -> Name -> TcM a
+-- It's important that this only calls pprTcTyThingCategory, which in
+-- turn does not look at the details of the TcTyThing.
+-- See Note [Placeholder PatSyn kinds] in TcBinds
wrongThingErr expected thing name
= failWithTc (pprTcTyThingCategory thing <+> quotes (ppr name) <+>
ptext (sLit "used as a") <+> text expected)