summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDr. ERDI Gergo <gergo@erdi.hu>2014-11-07 19:29:06 +0800
committerDr. ERDI Gergo <gergo@erdi.hu>2014-11-20 18:21:34 +0800
commitd4530b69ff9518a091cc1aabb2b75f2e9d5b275c (patch)
treec08f31981cba931276a8b77a98534ee27aeafefd
parent3b81309c057fc216afa053d195aaa85ee3a1ba9e (diff)
downloadhaskell-wip/T8584.tar.gz
Add support for pattern synonym type signatures.wip/T8584
Syntax is of the form pattern P :: (Prov b) => (Req a) => a -> b -> Int -> T a which declares a pattern synonym called `P`, with argument types `a`, `b`, and `Int`, and result type `T a`, with provided context `(Prov b)` and required context `(Req a)`.
-rw-r--r--compiler/hsSyn/HsBinds.lhs51
-rw-r--r--compiler/hsSyn/HsTypes.lhs16
-rw-r--r--compiler/iface/IfaceSyn.lhs25
-rw-r--r--compiler/iface/IfaceType.lhs15
-rw-r--r--compiler/parser/Parser.y51
-rw-r--r--compiler/parser/RdrHsSyn.hs27
-rw-r--r--compiler/rename/RnBinds.lhs42
-rw-r--r--compiler/typecheck/TcBinds.lhs214
-rw-r--r--compiler/typecheck/TcClassDcl.lhs4
-rw-r--r--compiler/typecheck/TcPat.lhs23
-rw-r--r--compiler/typecheck/TcPatSyn.lhs197
-rw-r--r--compiler/typecheck/TcPatSyn.lhs-boot9
-rw-r--r--docs/users_guide/glasgow_exts.xml15
-rw-r--r--testsuite/tests/ghci/scripts/T8776.stdout2
-rw-r--r--testsuite/tests/patsyn/should_compile/T8584-1.hs5
-rw-r--r--testsuite/tests/patsyn/should_compile/T8584-2.hs8
-rw-r--r--testsuite/tests/patsyn/should_compile/T8584-3.hs8
-rw-r--r--testsuite/tests/patsyn/should_compile/T8968-1.hs8
-rw-r--r--testsuite/tests/patsyn/should_compile/T8968-2.hs8
-rw-r--r--testsuite/tests/patsyn/should_compile/T8968-3.hs11
-rw-r--r--testsuite/tests/patsyn/should_compile/all.T6
m---------utils/haddock0
22 files changed, 483 insertions, 262 deletions
diff --git a/compiler/hsSyn/HsBinds.lhs b/compiler/hsSyn/HsBinds.lhs
index 95ec98ee30..b345e88a08 100644
--- a/compiler/hsSyn/HsBinds.lhs
+++ b/compiler/hsSyn/HsBinds.lhs
@@ -569,12 +569,12 @@ data Sig name
TypeSig [Located name] (LHsType name)
-- | A pattern synonym type signature
- -- @pattern (Eq b) => P a b :: (Num a) => T a
+ -- @pattern type forall b. (Eq b) => P a b :: forall a. (Num a) => T a
| PatSynSig (Located name)
- (HsPatSynDetails (LHsType name))
- (LHsType name) -- Type
+ (HsExplicitFlag, LHsTyVarBndrs name)
(LHsContext name) -- Provided context
- (LHsContext name) -- Required contex
+ (LHsContext name) -- Required context
+ (LHsType name)
-- | A type signature for a default method inside a class
--
@@ -731,34 +731,23 @@ ppr_sig (SpecSig var ty inl) = pragBrackets (pprSpec (unLoc var) (ppr ty) i
ppr_sig (InlineSig var inl) = pragBrackets (ppr inl <+> pprPrefixOcc (unLoc var))
ppr_sig (SpecInstSig ty) = pragBrackets (ptext (sLit "SPECIALIZE instance") <+> ppr ty)
ppr_sig (MinimalSig bf) = pragBrackets (pprMinimalSig bf)
-ppr_sig (PatSynSig name arg_tys ty prov req)
- = pprPatSynSig (unLoc name) False args (ppr ty) (pprCtx prov) (pprCtx req)
+ppr_sig (PatSynSig name (flag, qtvs) (L _ prov) (L _ req) ty)
+ = pprPatSynSig (unLoc name) False -- TODO: is_bindir
+ (pprHsForAll flag qtvs (noLoc []))
+ (pprHsContextMaybe prov) (pprHsContextMaybe req)
+ (ppr ty)
+
+pprPatSynSig :: (OutputableBndr name)
+ => name -> Bool -> SDoc -> Maybe SDoc -> Maybe SDoc -> SDoc -> SDoc
+pprPatSynSig ident _is_bidir tvs prov req ty
+ = ptext (sLit "pattern") <+> pprPrefixOcc ident <+> dcolon <+>
+ tvs <+> context <+> ty
where
- args = fmap ppr arg_tys
-
- pprCtx lctx = case unLoc lctx of
- [] -> Nothing
- ctx -> Just (pprHsContextNoArrow ctx)
-
-pprPatSynSig :: (OutputableBndr a)
- => a -> Bool -> HsPatSynDetails SDoc -> SDoc -> Maybe SDoc -> Maybe SDoc -> SDoc
-pprPatSynSig ident is_bidir args rhs_ty prov_theta req_theta
- = sep [ ptext (sLit "pattern")
- , thetaOpt prov_theta, name_and_args
- , colon
- , thetaOpt req_theta, rhs_ty
- ]
- where
- name_and_args = case args of
- PrefixPatSyn arg_tys ->
- pprPrefixOcc ident <+> sep arg_tys
- InfixPatSyn left_ty right_ty ->
- left_ty <+> pprInfixOcc ident <+> right_ty
-
- -- TODO: support explicit foralls
- thetaOpt = maybe empty (<+> darrow)
-
- colon = if is_bidir then dcolon else dcolon -- TODO
+ context = case (prov, req) of
+ (Nothing, Nothing) -> empty
+ (Nothing, Just req) -> parens empty <+> darrow <+> req <+> darrow
+ (Just prov, Nothing) -> prov <+> darrow
+ (Just prov, Just req) -> prov <+> darrow <+> req <+> darrow
instance OutputableBndr name => Outputable (FixitySig name) where
ppr (FixitySig name fixity) = sep [ppr fixity, pprInfixOcc (unLoc name)]
diff --git a/compiler/hsSyn/HsTypes.lhs b/compiler/hsSyn/HsTypes.lhs
index 9bd5845a45..4a01948430 100644
--- a/compiler/hsSyn/HsTypes.lhs
+++ b/compiler/hsSyn/HsTypes.lhs
@@ -43,7 +43,8 @@ module HsTypes (
splitHsAppTys, hsTyGetAppHead_maybe, mkHsAppTys, mkHsOpTy,
-- Printing
- pprParendHsType, pprHsForAll, pprHsContext, pprHsContextNoArrow,
+ pprParendHsType, pprHsForAll,
+ pprHsContext, pprHsContextNoArrow, pprHsContextMaybe
) where
import {-# SOURCE #-} HsExpr ( HsSplice, pprUntypedSplice )
@@ -63,6 +64,7 @@ import Outputable
import FastString
import Data.Data hiding ( Fixity )
+import Data.Maybe ( fromMaybe )
\end{code}
@@ -604,13 +606,15 @@ pprHsForAll exp qtvs cxt
forall_part = forAllLit <+> ppr qtvs <> dot
pprHsContext :: (OutputableBndr name) => HsContext name -> SDoc
-pprHsContext [] = empty
-pprHsContext cxt = pprHsContextNoArrow cxt <+> darrow
+pprHsContext = maybe empty (<+> darrow) . pprHsContextMaybe
pprHsContextNoArrow :: (OutputableBndr name) => HsContext name -> SDoc
-pprHsContextNoArrow [] = empty
-pprHsContextNoArrow [L _ pred] = ppr_mono_ty FunPrec pred
-pprHsContextNoArrow cxt = parens (interpp'SP cxt)
+pprHsContextNoArrow = fromMaybe empty . pprHsContextMaybe
+
+pprHsContextMaybe :: (OutputableBndr name) => HsContext name -> Maybe SDoc
+pprHsContextMaybe [] = Nothing
+pprHsContextMaybe [L _ pred] = Just $ ppr_mono_ty FunPrec pred
+pprHsContextMaybe cxt = Just $ parens (interpp'SP cxt)
pprConDeclFields :: OutputableBndr name => [ConDeclField name] -> SDoc
pprConDeclFields fields = braces (sep (punctuate comma (map ppr_fld fields)))
diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs
index c2b7c5276b..49d645d32b 100644
--- a/compiler/iface/IfaceSyn.lhs
+++ b/compiler/iface/IfaceSyn.lhs
@@ -760,24 +760,19 @@ pprIfaceDecl ss (IfaceSyn { ifName = tycon, ifTyVars = tyvars
pp_branches _ = Outputable.empty
pprIfaceDecl _ (IfacePatSyn { ifName = name, ifPatWorker = worker,
- ifPatIsInfix = is_infix,
- ifPatUnivTvs = _univ_tvs, ifPatExTvs = _ex_tvs,
+ ifPatUnivTvs = univ_tvs, ifPatExTvs = ex_tvs,
ifPatProvCtxt = prov_ctxt, ifPatReqCtxt = req_ctxt,
- ifPatArgs = args,
- ifPatTy = ty })
- = pprPatSynSig name is_bidirectional args' ty' (pprCtxt prov_ctxt) (pprCtxt req_ctxt)
+ ifPatArgs = arg_tys,
+ ifPatTy = pat_ty} )
+ = pprPatSynSig name is_bidirectional
+ (pprUserIfaceForAll tvs)
+ (pprIfaceContextMaybe prov_ctxt)
+ (pprIfaceContextMaybe req_ctxt)
+ (pprIfaceType ty)
where
is_bidirectional = isJust worker
- args' = case (is_infix, args) of
- (True, [left_ty, right_ty]) ->
- InfixPatSyn (pprParendIfaceType left_ty) (pprParendIfaceType right_ty)
- (_, tys) ->
- PrefixPatSyn (map pprParendIfaceType tys)
-
- ty' = pprParendIfaceType ty
-
- pprCtxt [] = Nothing
- pprCtxt ctxt = Just $ pprIfaceContext ctxt
+ tvs = univ_tvs ++ ex_tvs
+ ty = foldr IfaceFunTy pat_ty arg_tys
pprIfaceDecl ss (IfaceId { ifName = var, ifType = ty,
ifIdDetails = details, ifIdInfo = info })
diff --git a/compiler/iface/IfaceType.lhs b/compiler/iface/IfaceType.lhs
index aae61c47ed..223a25b8b4 100644
--- a/compiler/iface/IfaceType.lhs
+++ b/compiler/iface/IfaceType.lhs
@@ -27,7 +27,8 @@ module IfaceType (
toIfaceCoercion,
-- Printing
- pprIfaceType, pprParendIfaceType, pprIfaceContext, pprIfaceContextArr,
+ pprIfaceType, pprParendIfaceType,
+ pprIfaceContext, pprIfaceContextArr, pprIfaceContextMaybe,
pprIfaceIdBndr, pprIfaceLamBndr, pprIfaceTvBndr, pprIfaceTvBndrs,
pprIfaceBndrs, pprIfaceTcArgs, pprParendIfaceTcArgs,
pprIfaceForAllPart, pprIfaceForAll, pprIfaceSigmaType,
@@ -63,6 +64,7 @@ import Binary
import Outputable
import FastString
import UniqSet
+import Data.Maybe( fromMaybe )
\end{code}
%************************************************************************
@@ -703,12 +705,15 @@ instance Binary IfaceTcArgs where
-------------------
pprIfaceContextArr :: Outputable a => [a] -> SDoc
-- Prints "(C a, D b) =>", including the arrow
-pprIfaceContextArr [] = empty
-pprIfaceContextArr theta = pprIfaceContext theta <+> darrow
+pprIfaceContextArr = maybe empty (<+> darrow) . pprIfaceContextMaybe
pprIfaceContext :: Outputable a => [a] -> SDoc
-pprIfaceContext [pred] = ppr pred -- No parens
-pprIfaceContext preds = parens (fsep (punctuate comma (map ppr preds)))
+pprIfaceContext = fromMaybe (parens empty) . pprIfaceContextMaybe
+
+pprIfaceContextMaybe :: Outputable a => [a] -> Maybe SDoc
+pprIfaceContextMaybe [] = Nothing
+pprIfaceContextMaybe [pred] = Just $ ppr pred -- No parens
+pprIfaceContextMaybe preds = Just $ parens (fsep (punctuate comma (map ppr preds)))
instance Binary IfaceType where
put_ bh (IfaceForAllTy aa ab) = do
diff --git a/compiler/parser/Parser.y b/compiler/parser/Parser.y
index 6f6422fdbe..eb528c35dd 100644
--- a/compiler/parser/Parser.y
+++ b/compiler/parser/Parser.y
@@ -866,29 +866,47 @@ role : VARID { sL1 $1 $ Just $ getVARID $1 }
-- Glasgow extension: pattern synonyms
pattern_synonym_decl :: { LHsDecl RdrName }
- : 'pattern' pat '=' pat
- {% do { (name, args) <- splitPatSyn $2
- ; return $ sLL $1 $> . ValD $ mkPatSynBind name args $4 ImplicitBidirectional
- }}
- | 'pattern' pat '<-' pat
- {% do { (name, args) <- splitPatSyn $2
- ; return $ sLL $1 $> . ValD $ mkPatSynBind name args $4 Unidirectional
- }}
- | 'pattern' pat '<-' pat where_decls
- {% do { (name, args) <- splitPatSyn $2
- ; mg <- toPatSynMatchGroup name $5
+ : 'pattern' pattern_synonym_lhs '=' pat
+ { let (name, args) = $2
+ in sLL $1 $> . ValD $ mkPatSynBind name args $4 ImplicitBidirectional }
+ | 'pattern' pattern_synonym_lhs '<-' pat
+ { let (name, args) = $2
+ in sLL $1 $> . ValD $ mkPatSynBind name args $4 Unidirectional }
+ | 'pattern' pattern_synonym_lhs '<-' pat where_decls
+ {% do { let (name, args) = $2
+ ; mg <- mkPatSynMatchGroup name $5
; return $ sLL $1 $> . ValD $
- mkPatSynBind name args $4 (ExplicitBidirectional mg)
- }}
+ mkPatSynBind name args $4 (ExplicitBidirectional mg) }}
-where_decls :: { Located (OrdList (LHsDecl RdrName)) }
- : 'where' '{' decls '}' { $3 }
- | 'where' vocurly decls close { $3 }
+pattern_synonym_lhs :: { (Located RdrName, HsPatSynDetails (Located RdrName)) }
+ : con vars0 { ($1, PrefixPatSyn $2) }
+ | varid consym varid { ($2, InfixPatSyn $1 $3) }
vars0 :: { [Located RdrName] }
: {- empty -} { [] }
| varid vars0 { $1 : $2 }
+where_decls :: { Located (OrdList (LHsDecl RdrName)) }
+ : 'where' '{' decls '}' { $3 }
+ | 'where' vocurly decls close { $3 }
+
+pattern_synonym_sig :: { LSig RdrName }
+ : 'pattern' con '::' ptype
+ { let (flag, qtvs, prov, req, ty) = unLoc $4
+ in sLL $1 $> $ PatSynSig $2 (flag, mkHsQTvs qtvs) prov req ty }
+
+ptype :: { Located (HsExplicitFlag, [LHsTyVarBndr RdrName], LHsContext RdrName, LHsContext RdrName, LHsType RdrName) }
+ : 'forall' tv_bndrs '.' ptype
+ {% do { hintExplicitForall (getLoc $1)
+ ; let (_, qtvs', prov, req, ty) = unLoc $4
+ ; return $ sLL $1 $> (Explicit, $2 ++ qtvs', prov, req ,ty) }}
+ | context '=>' context '=>' type
+ { sLL $1 $> (Implicit, [], $1, $3, $5) }
+ | context '=>' type
+ { sLL $1 $> (Implicit, [], $1, noLoc [], $3) }
+ | type
+ { sL1 $1 (Implicit, [], noLoc [], noLoc [], $1) }
+
-----------------------------------------------------------------------------
-- Nested declarations
@@ -1496,6 +1514,7 @@ sigdecl :: { Located (OrdList (LHsDecl RdrName)) }
{ sLL $1 $> $ toOL [ sLL $1 $> $ SigD (TypeSig ($1 : reverse (unLoc $3)) $5) ] }
| infix prec ops { sLL $1 $> $ toOL [ sLL $1 $> $ SigD (FixSig (FixitySig n (Fixity $2 (unLoc $1))))
| n <- unLoc $3 ] }
+ | pattern_synonym_sig { sLL $1 $> $ unitOL $ sLL $1 $> . SigD . unLoc $ $1 }
| '{-# INLINE' activation qvar '#-}'
{ sLL $1 $> $ unitOL (sLL $1 $> $ SigD (InlineSig $3 (mkInlinePragma (getINLINE $1) $2))) }
| '{-# SPECIALISE' activation qvar '::' sigtypes1 '#-}'
diff --git a/compiler/parser/RdrHsSyn.hs b/compiler/parser/RdrHsSyn.hs
index 625c4dc6e9..e945e43362 100644
--- a/compiler/parser/RdrHsSyn.hs
+++ b/compiler/parser/RdrHsSyn.hs
@@ -18,7 +18,7 @@ module RdrHsSyn (
mkTyFamInst,
mkFamDecl,
splitCon, mkInlinePragma,
- splitPatSyn, toPatSynMatchGroup,
+ mkPatSynMatchGroup,
mkRecConstrOrUpdate, -- HsExp -> [HsFieldUpdate] -> P HsExp
mkTyClD, mkInstD,
@@ -414,33 +414,16 @@ splitCon ty
mk_rest [L _ (HsRecTy flds)] = RecCon flds
mk_rest ts = PrefixCon ts
-splitPatSyn :: LPat RdrName
- -> P (Located RdrName, HsPatSynDetails (Located RdrName))
-splitPatSyn (L _ (ParPat pat)) = splitPatSyn pat
-splitPatSyn pat@(L loc (ConPatIn con details)) = do
- details' <- case details of
- PrefixCon pats -> liftM PrefixPatSyn (mapM patVar pats)
- InfixCon pat1 pat2 -> liftM2 InfixPatSyn (patVar pat1) (patVar pat2)
- RecCon{} -> recordPatSynErr loc pat
- return (con, details')
- where
- patVar :: LPat RdrName -> P (Located RdrName)
- patVar (L loc (VarPat v)) = return $ L loc v
- patVar (L _ (ParPat pat)) = patVar pat
- patVar (L loc pat) = parseErrorSDoc loc $
- text "Pattern synonym arguments must be variable names:" $$
- ppr pat
-splitPatSyn pat@(L loc _) = parseErrorSDoc loc $
- text "invalid pattern synonym declaration:" $$ ppr pat
-
recordPatSynErr :: SrcSpan -> LPat RdrName -> P a
recordPatSynErr loc pat =
parseErrorSDoc loc $
text "record syntax not supported for pattern synonym declarations:" $$
ppr pat
-toPatSynMatchGroup :: Located RdrName -> Located (OrdList (LHsDecl RdrName)) -> P (MatchGroup RdrName (LHsExpr RdrName))
-toPatSynMatchGroup (L _ patsyn_name) (L _ decls) =
+mkPatSynMatchGroup :: Located RdrName
+ -> Located (OrdList (LHsDecl RdrName))
+ -> P (MatchGroup RdrName (LHsExpr RdrName))
+mkPatSynMatchGroup (L _ patsyn_name) (L _ decls) =
do { matches <- mapM fromDecl (fromOL decls)
; return $ mkMatchGroup FromSource matches }
where
diff --git a/compiler/rename/RnBinds.lhs b/compiler/rename/RnBinds.lhs
index c2489cbac9..80239e9586 100644
--- a/compiler/rename/RnBinds.lhs
+++ b/compiler/rename/RnBinds.lhs
@@ -30,7 +30,7 @@ import {-# SOURCE #-} RnExpr( rnLExpr, rnStmts )
import HsSyn
import TcRnMonad
import TcEvidence ( emptyTcEvBinds )
-import RnTypes ( bindSigTyVarsFV, rnHsSigType, rnLHsType, checkPrecMatch, rnContext )
+import RnTypes
import RnPat
import RnNames
import RnEnv
@@ -841,23 +841,29 @@ renameSig ctxt sig@(MinimalSig bf)
= do new_bf <- traverse (lookupSigOccRn ctxt sig) bf
return (MinimalSig new_bf, emptyFVs)
-renameSig ctxt sig@(PatSynSig v args ty prov req)
- = do v' <- lookupSigOccRn ctxt sig v
- let doc = quotes (ppr v)
- rn_type = rnHsSigType doc
- (ty', fvs1) <- rn_type ty
- (args', fvs2) <- case args of
- PrefixPatSyn tys ->
- do (tys, fvs) <- unzip <$> mapM rn_type tys
- return (PrefixPatSyn tys, plusFVs fvs)
- InfixPatSyn left right ->
- do (left', fvs1) <- rn_type left
- (right', fvs2) <- rn_type right
- return (InfixPatSyn left' right', fvs1 `plusFV` fvs2)
- (prov', fvs3) <- rnContext (TypeSigCtx doc) prov
- (req', fvs4) <- rnContext (TypeSigCtx doc) req
- let fvs = plusFVs [fvs1, fvs2, fvs3, fvs4]
- return (PatSynSig v' args' ty' prov' req', fvs)
+renameSig ctxt sig@(PatSynSig v (flag, qtvs) prov req ty)
+ = do { v' <- lookupSigOccRn ctxt sig v
+ ; let doc = TypeSigCtx $ quotes (ppr v)
+ ; loc <- getSrcSpanM
+
+ ; let (tv_kvs, mentioned) = extractHsTysRdrTyVars (ty:unLoc prov ++ unLoc req)
+ ; tv_bndrs <- case flag of
+ Implicit ->
+ return $ mkHsQTvs . userHsTyVarBndrs loc $ mentioned
+ Explicit ->
+ do { let heading = ptext (sLit "In the pattern synonym type signature")
+ <+> quotes (ppr sig)
+ ; warnUnusedForAlls (heading $$ docOfHsDocContext doc) qtvs mentioned
+ ; return qtvs }
+ Qualified -> panic "renameSig: Qualified"
+
+ ; bindHsTyVars doc Nothing tv_kvs tv_bndrs $ \ tyvars -> do
+ { (prov', fvs1) <- rnContext doc prov
+ ; (req', fvs2) <- rnContext doc req
+ ; (ty', fvs3) <- rnLHsType doc ty
+
+ ; let fvs = plusFVs [fvs1, fvs2, fvs3]
+ ; return (PatSynSig v' (flag, tyvars) prov' req' ty', fvs) }}
ppr_sig_bndrs :: [Located RdrName] -> SDoc
ppr_sig_bndrs bs = quotes (pprWithCommas ppr bs)
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index c2af40703d..ec5f9d777a 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -9,14 +9,14 @@
module TcBinds ( tcLocalBinds, tcTopBinds, tcRecSelBinds,
tcHsBootSigs, tcPolyCheck,
- PragFun, tcSpecPrags, tcVectDecls, mkPragFun,
- TcSigInfo(..), TcSigFun,
+ PragFun, tcSpecPrags, tcVectDecls, mkPragFun,
+ TcSigInfo(..), TcSigFun,
instTcTySig, instTcTySigFromId, findScopedTyVars,
badBootDeclErr ) where
import {-# SOURCE #-} TcMatches ( tcGRHSsPat, tcMatchesFun )
import {-# SOURCE #-} TcExpr ( tcMonoExpr )
-import {-# SOURCE #-} TcPatSyn ( tcPatSynDecl, tcPatSynWorker )
+import {-# SOURCE #-} TcPatSyn ( tcInferPatSynDecl, tcCheckPatSynDecl, tcPatSynWorker )
import DynFlags
import HsSyn
@@ -33,7 +33,7 @@ import PatSyn
import ConLike
import FamInstEnv( normaliseType )
import FamInst( tcGetFamInstEnvs )
-import Type( tidyOpenType )
+import Type( tidyOpenType, splitFunTys )
import TyCon
import TcType
import TysPrim
@@ -61,6 +61,7 @@ import PrelNames(ipClassName)
import TcValidity (checkValidType)
import Control.Monad
+import Data.List (partition)
#include "HsVersions.h"
\end{code}
@@ -99,10 +100,10 @@ dictionaries, which we resolve at the module level.
Note [Polymorphic recursion]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The game plan for polymorphic recursion in the code above is
+The game plan for polymorphic recursion in the code above is
* Bind any variable for which we have a type signature
- to an Id with a polymorphic type. Then when type-checking
+ to an Id with a polymorphic type. Then when type-checking
the RHSs we'll make a full polymorphic call.
This fine, but if you aren't a bit careful you end up with a horrendous
@@ -174,7 +175,7 @@ tcTopBinds (ValBindsOut binds sigs)
, tcg_imp_specs = specs ++ tcg_imp_specs tcg_env } }
; return (tcg_env', tcl_env) }
- -- The top level bindings are flattened into a giant
+ -- The top level bindings are flattened into a giant
-- implicitly-mutually-recursive LHsBinds
tcTopBinds (ValBindsIn {}) = panic "tcTopBinds"
@@ -183,12 +184,12 @@ tcRecSelBinds :: HsValBinds Name -> TcM TcGblEnv
tcRecSelBinds (ValBindsOut binds sigs)
= tcExtendGlobalValEnv [sel_id | L _ (IdSig sel_id) <- sigs] $
do { (rec_sel_binds, tcg_env) <- discardWarnings (tcValBinds TopLevel binds sigs getGblEnv)
- ; let tcg_env'
+ ; let tcg_env'
| isHsBootOrSig (tcg_src tcg_env) = tcg_env
| otherwise = tcg_env { tcg_binds = foldr (unionBags . snd)
(tcg_binds tcg_env)
rec_sel_binds }
- -- Do not add the code for record-selector bindings when
+ -- Do not add the code for record-selector bindings when
-- compiling hs-boot files
; return tcg_env' }
tcRecSelBinds (ValBindsIn {}) = panic "tcRecSelBinds"
@@ -215,7 +216,7 @@ badBootDeclErr = ptext (sLit "Illegal declarations in an hs-boot file")
tcLocalBinds :: HsLocalBinds Name -> TcM thing
-> TcM (HsLocalBinds TcId, thing)
-tcLocalBinds EmptyLocalBinds thing_inside
+tcLocalBinds EmptyLocalBinds thing_inside
= do { thing <- thing_inside
; return (EmptyLocalBinds, thing) }
@@ -229,10 +230,10 @@ tcLocalBinds (HsIPBinds (IPBinds ip_binds _)) thing_inside
; (given_ips, ip_binds') <-
mapAndUnzipM (wrapLocSndM (tc_ip_bind ipClass)) ip_binds
- -- If the binding binds ?x = E, we must now
+ -- If the binding binds ?x = E, we must now
-- discharge any ?x constraints in expr_lie
-- See Note [Implicit parameter untouchables]
- ; (ev_binds, result) <- checkConstraints (IPSkol ips)
+ ; (ev_binds, result) <- checkConstraints (IPSkol ips)
[] given_ips thing_inside
; return (HsIPBinds (IPBinds ip_binds' ev_binds), result) }
@@ -268,11 +269,11 @@ as untouchables, not so much because we really must not unify them,
but rather because we otherwise end up with constraints like this
Num alpha, Implic { wanted = alpha ~ Int }
The constraint solver solves alpha~Int by unification, but then
-doesn't float that solved constraint out (it's not an unsolved
+doesn't float that solved constraint out (it's not an unsolved
wanted). Result disaster: the (Num alpha) is again solved, this
time by defaulting. No no no.
-However [Oct 10] this is all handled automatically by the
+However [Oct 10] this is all handled automatically by the
untouchable-range idea.
Note [Placeholder PatSyn kinds]
@@ -300,10 +301,10 @@ tcTyVar, doesn't look inside the TcTyThing.
\begin{code}
-tcValBinds :: TopLevelFlag
+tcValBinds :: TopLevelFlag
-> [(RecFlag, LHsBinds Name)] -> [LSig Name]
-> TcM thing
- -> TcM ([(RecFlag, LHsBinds TcId)], thing)
+ -> TcM ([(RecFlag, LHsBinds TcId)], thing)
tcValBinds top_lvl binds sigs thing_inside
= do { -- Typecheck the signature
@@ -313,7 +314,7 @@ tcValBinds top_lvl binds sigs thing_inside
; let prag_fn = mkPragFun sigs (foldr (unionBags . snd) emptyBag binds)
- -- Extend the envt right away with all
+ -- Extend the envt right away with all
-- the Ids declared with type signatures
-- Use tcExtendIdEnv2 to avoid extending the TcIdBinder stack
; tcExtendIdEnv2 [(idName id, id) | id <- poly_ids] $ do
@@ -339,7 +340,7 @@ tcBindGroups :: TopLevelFlag -> TcSigFun -> PragFun
-- Typecheck a whole lot of value bindings,
-- one strongly-connected component at a time
-- Here a "strongly connected component" has the strightforward
--- meaning of a group of bindings that mention each other,
+-- meaning of a group of bindings that mention each other,
-- ignoring type signatures (that part comes later)
tcBindGroups _ _ _ [] thing_inside
@@ -348,18 +349,18 @@ tcBindGroups _ _ _ [] thing_inside
tcBindGroups top_lvl sig_fn prag_fn (group : groups) thing_inside
= do { (group', (groups', thing))
- <- tc_group top_lvl sig_fn prag_fn group $
+ <- tc_group top_lvl sig_fn prag_fn group $
tcBindGroups top_lvl sig_fn prag_fn groups thing_inside
; return (group' ++ groups', thing) }
------------------------
-tc_group :: forall thing.
+tc_group :: forall thing.
TopLevelFlag -> TcSigFun -> PragFun
-> (RecFlag, LHsBinds Name) -> TcM thing
-> TcM ([(RecFlag, LHsBinds TcId)], thing)
-- Typecheck one strongly-connected component of the original program.
--- We get a list of groups back, because there may
+-- We get a list of groups back, because there may
-- be specialisations etc as well
tc_group top_lvl sig_fn prag_fn (NonRecursive, binds) thing_inside
@@ -374,8 +375,8 @@ tc_group top_lvl sig_fn prag_fn (NonRecursive, binds) thing_inside
; return ( [(NonRecursive, bind')], thing) }
tc_group top_lvl sig_fn prag_fn (Recursive, binds) thing_inside
- = -- To maximise polymorphism, we do a new
- -- strongly-connected-component analysis, this time omitting
+ = -- To maximise polymorphism, we do a new
+ -- strongly-connected-component analysis, this time omitting
-- any references to variables with type signatures.
-- (This used to be optional, but isn't now.)
do { traceTc "tc_group rec" (pprLHsBinds binds)
@@ -395,7 +396,7 @@ tc_group top_lvl sig_fn prag_fn (Recursive, binds) thing_inside
go :: [SCC (LHsBind Name)] -> TcM (LHsBinds TcId, [TcId], thing)
go (scc:sccs) = do { (binds1, ids1, closed) <- tc_scc scc
- ; (binds2, ids2, thing) <- tcExtendLetEnv top_lvl closed ids1 $
+ ; (binds2, ids2, thing) <- tcExtendLetEnv top_lvl closed ids1 $
go sccs
; return (binds1 `unionBags` binds2, ids1 ++ ids2, thing) }
go [] = do { thing <- thing_inside; return (emptyBag, [], thing) }
@@ -419,9 +420,8 @@ tc_single :: forall thing.
TopLevelFlag -> TcSigFun -> PragFun
-> LHsBind Name -> TcM thing
-> TcM (LHsBinds TcId, thing)
-tc_single _top_lvl _sig_fn _prag_fn (L _ (PatSynBind psb)) thing_inside
- = do { (pat_syn, aux_binds) <- tcPatSynDecl psb
-
+tc_single _top_lvl sig_fn _prag_fn (L _ (PatSynBind psb@PSB{ psb_id = L _ name })) thing_inside
+ = do { (pat_syn, aux_binds) <- tc_pat_syn_decl
; let tything = AConLike (PatSynCon pat_syn)
implicit_ids = (patSynMatcher pat_syn) :
(maybeToList (patSynWorker pat_syn))
@@ -431,13 +431,19 @@ tc_single _top_lvl _sig_fn _prag_fn (L _ (PatSynBind psb)) thing_inside
thing_inside
; return (aux_binds, thing)
}
+ where
+ tc_pat_syn_decl = case sig_fn name of
+ Nothing -> tcInferPatSynDecl psb
+ Just (TcPatSynInfo tpsi) -> tcCheckPatSynDecl psb tpsi
+ Just _ -> panic "tc_single"
+
tc_single top_lvl sig_fn prag_fn lbind thing_inside
= do { (binds1, ids, closed) <- tcPolyBinds top_lvl sig_fn prag_fn
NonRecursive NonRecursive
[lbind]
; thing <- tcExtendLetEnv top_lvl closed ids thing_inside
; return (binds1, thing) }
-
+
------------------------
mkEdges :: TcSigFun -> LHsBinds Name
-> [(LHsBind Name, BKey, [BKey])]
@@ -474,26 +480,26 @@ tcPolyBinds :: TopLevelFlag -> TcSigFun -> PragFun
-> [LHsBind Name]
-> TcM (LHsBinds TcId, [TcId], TopLevelFlag)
--- Typechecks a single bunch of bindings all together,
+-- Typechecks a single bunch of bindings all together,
-- and generalises them. The bunch may be only part of a recursive
-- group, because we use type signatures to maximise polymorphism
--
-- Returns a list because the input may be a single non-recursive binding,
-- in which case the dependency order of the resulting bindings is
--- important.
---
+-- important.
+--
-- Knows nothing about the scope of the bindings
tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
= setSrcSpan loc $
- recoverM (recoveryCode binder_names sig_fn) $ do
+ recoverM (recoveryCode binder_names sig_fn) $ do
-- Set up main recover; take advantage of any type sigs
{ traceTc "------------------------------------------------" Outputable.empty
; traceTc "Bindings for {" (ppr binder_names)
; dflags <- getDynFlags
; type_env <- getLclTypeEnv
- ; let plan = decideGeneralisationPlan dflags type_env
+ ; let plan = decideGeneralisationPlan dflags type_env
binder_names bind_list sig_fn
; traceTc "Generalisation plan" (ppr plan)
; result@(tc_binds, poly_ids, _) <- case plan of
@@ -513,7 +519,7 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
where
binder_names = collectHsBindListBinders bind_list
loc = foldr1 combineSrcSpans (map getLoc bind_list)
- -- The mbinds have been dependency analysed and
+ -- The mbinds have been dependency analysed and
-- may no longer be adjacent; so find the narrowest
-- span that includes them all
@@ -527,7 +533,7 @@ tcPolyNoGen -- No generalisation whatsoever
tcPolyNoGen rec_tc prag_fn tc_sig_fn bind_list
= do { (binds', mono_infos) <- tcMonoBinds rec_tc tc_sig_fn
- (LetGblBndr prag_fn)
+ (LetGblBndr prag_fn)
bind_list
; mono_ids' <- mapM tc_mono_info mono_infos
; return (binds', mono_ids', NotTopLevel) }
@@ -546,22 +552,22 @@ tcPolyNoGen rec_tc prag_fn tc_sig_fn bind_list
------------------
tcPolyCheck :: RecFlag -- Whether it's recursive after breaking
-- dependencies based on type signatures
- -> PragFun -> TcSigInfo
+ -> PragFun -> TcSigInfo
-> LHsBind Name
-> TcM (LHsBinds TcId, [TcId], TopLevelFlag)
--- There is just one binding,
+-- There is just one binding,
-- it binds a single variable,
-- it has a signature,
tcPolyCheck rec_tc prag_fn
- sig@(TcSigInfo { sig_id = poly_id, sig_tvs = tvs_w_scoped
+ sig@(TcSigInfo { sig_id = poly_id, sig_tvs = tvs_w_scoped
, sig_theta = theta, sig_tau = tau, sig_loc = loc })
bind
= do { ev_vars <- newEvVars theta
; let skol_info = SigSkol (FunSigCtxt (idName poly_id)) (mkPhiTy theta tau)
prag_sigs = prag_fn (idName poly_id)
tvs = map snd tvs_w_scoped
- ; (ev_binds, (binds', [mono_info]))
- <- setSrcSpan loc $
+ ; (ev_binds, (binds', [mono_info]))
+ <- setSrcSpan loc $
checkConstraints skol_info tvs ev_vars $
tcExtendTyVarEnv2 [(n,tv) | (Just n, tv) <- tvs_w_scoped] $
tcMonoBinds rec_tc (\_ -> Just sig) LetLclBndr [bind]
@@ -574,7 +580,7 @@ tcPolyCheck rec_tc prag_fn
, abe_poly = poly_id
, abe_mono = mono_id
, abe_prags = SpecPrags spec_prags }
- abs_bind = L loc $ AbsBinds
+ abs_bind = L loc $ AbsBinds
{ abs_tvs = tvs
, abs_ev_vars = ev_vars, abs_ev_binds = ev_binds
, abs_exports = [export], abs_binds = binds' }
@@ -582,11 +588,14 @@ tcPolyCheck rec_tc prag_fn
| otherwise = NotTopLevel
; return (unitBag abs_bind, [poly_id], closed) }
+tcPolyCheck _rec_tc _prag_fn sig _bind
+ = pprPanic "tcPolyCheck" (ppr sig)
+
------------------
-tcPolyInfer
+tcPolyInfer
:: RecFlag -- Whether it's recursive after breaking
-- dependencies based on type signatures
- -> PragFun -> TcSigFun
+ -> PragFun -> TcSigFun
-> Bool -- True <=> apply the monomorphism restriction
-> Bool -- True <=> free vars have closed types
-> [LHsBind Name]
@@ -608,7 +617,7 @@ tcPolyInfer rec_tc prag_fn tc_sig_fn mono closed bind_list
; let poly_ids = map abe_poly exports
final_closed | closed && not mr_bites = TopLevel
| otherwise = NotTopLevel
- abs_bind = L loc $
+ abs_bind = L loc $
AbsBinds { abs_tvs = qtvs
, abs_ev_vars = givens, abs_ev_binds = ev_binds
, abs_exports = exports, abs_binds = binds' }
@@ -640,7 +649,8 @@ mkExport prag_fn qtvs theta (poly_name, mb_sig, mono_id)
= do { mono_ty <- zonkTcType (idType mono_id)
; poly_id <- case mb_sig of
- Just sig -> return (sig_id sig)
+ Just TcSigInfo{ sig_id = id } -> return id
+ Just _ -> panic "mkExport"
Nothing -> mkInferredPolyId poly_name qtvs theta mono_ty
-- NB: poly_id has a zonked type
@@ -715,7 +725,7 @@ mk_bind_msg inferred want_ambig poly_name poly_ty tidy_env
Note [Validity of inferred types]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We need to check inferred type for validity, in case it uses language
+We need to check inferred type for validity, in case it uses language
extensions that are not turned on. The principle is that if the user
simply adds the inferred type to the program source, it'll compile fine.
See #8883.
@@ -726,7 +736,7 @@ Examples that might fail:
- an inferred type that includes unboxed tuples
However we don't do the ambiguity check (checkValidType omits it for
-InfSigCtxt) because the impedence-matching stage, which follows
+InfSigCtxt) because the impedence-matching stage, which follows
immediately, will do it and we don't want two error messages.
Moreover, because of the impedence matching stage, the ambiguity-check
suggestion of -XAllowAmbiguiousTypes will not work.
@@ -742,8 +752,8 @@ Consider
g _ y = f 9 y
After typechecking we'll get
- f_mono_ty :: a -> Bool -> Bool
- g_mono_ty :: [b] -> Bool -> Bool
+ f_mono_ty :: a -> Bool -> Bool
+ g_mono_ty :: [b] -> Bool -> Bool
with constraints
(Eq a, Num a)
@@ -760,9 +770,9 @@ We can get these by "impedence matching":
g b = case tuple Integer b dEqInteger dNumInteger of (f,g) -> g
Suppose the shared quantified tyvars are qtvs and constraints theta.
-Then we want to check that
+Then we want to check that
f's polytype is more polymorphic than forall qtvs. theta => f_mono_ty
-and the proof is the impedence matcher.
+and the proof is the impedence matcher.
Notice that the impedence matcher may do defaulting. See Trac #7173.
@@ -826,7 +836,7 @@ tcSpecPrags poly_id prag_sigs
--------------
tcSpec :: TcId -> Sig Name -> TcM TcSpecPrag
-tcSpec poly_id prag@(SpecSig fun_name hs_ty inl)
+tcSpec poly_id prag@(SpecSig fun_name hs_ty inl)
-- The Name fun_name in the SpecSig may not be the same as that of the poly_id
-- Example: SPECIALISE for a class method: the Name in the SpecSig is
-- for the selector Id, but the poly_id is something like $cop
@@ -835,7 +845,7 @@ tcSpec poly_id prag@(SpecSig fun_name hs_ty inl)
= addErrCtxt (spec_ctxt prag) $
do { spec_ty <- tcHsSigType sig_ctxt hs_ty
; warnIf (not (isOverloadedTy poly_ty || isInlinePragma inl))
- (ptext (sLit "SPECIALISE pragma for non-overloaded function")
+ (ptext (sLit "SPECIALISE pragma for non-overloaded function")
<+> quotes (ppr fun_name))
-- Note [SPECIALISE pragmas]
; wrap <- tcSubType origin sig_ctxt (idType poly_id) spec_ty
@@ -858,14 +868,14 @@ tcImpPrags prags
; if (not_specialising dflags) then
return []
else
- mapAndRecoverM (wrapLocM tcImpSpec)
+ mapAndRecoverM (wrapLocM tcImpSpec)
[L loc (name,prag) | (L loc prag@(SpecSig (L _ name) _ _)) <- prags
, not (nameIsLocalOrFrom this_mod name) ] }
where
-- Ignore SPECIALISE pragmas for imported things
-- when we aren't specialising, or when we aren't generating
-- code. The latter happens when Haddocking the base library;
- -- we don't wnat complaints about lack of INLINABLE pragmas
+ -- we don't wnat complaints about lack of INLINABLE pragmas
not_specialising dflags
| not (gopt Opt_Specialise dflags) = True
| otherwise = case hscTarget dflags of
@@ -884,7 +894,7 @@ impSpecErr :: Name -> SDoc
impSpecErr name
= hang (ptext (sLit "You cannot SPECIALISE") <+> quotes (ppr name))
2 (vcat [ ptext (sLit "because its definition has no INLINE/INLINABLE pragma")
- , parens $ sep
+ , parens $ sep
[ ptext (sLit "or its defining module") <+> quotes (ppr mod)
, ptext (sLit "was compiled without -O")]])
where
@@ -892,7 +902,7 @@ impSpecErr name
--------------
tcVectDecls :: [LVectDecl Name] -> TcM ([LVectDecl TcId])
-tcVectDecls decls
+tcVectDecls decls
= do { decls' <- mapM (wrapLocM tcVect) decls
; let ids = [lvectDeclName decl | decl <- decls', not $ lvectInstDecl decl]
dups = findDupsEq (==) ids
@@ -901,7 +911,7 @@ tcVectDecls decls
; return decls'
}
where
- reportVectDups (first:_second:_more)
+ reportVectDups (first:_second:_more)
= addErrAt (getSrcSpan first) $
ptext (sLit "Duplicate vectorisation declarations for") <+> ppr first
reportVectDups _ = return ()
@@ -923,25 +933,25 @@ tcVect (HsVect name rhs)
{- OLD CODE:
-- turn the vectorisation declaration into a single non-recursive binding
- ; let bind = L loc $ mkTopFunBind name [mkSimpleMatch [] rhs]
+ ; let bind = L loc $ mkTopFunBind name [mkSimpleMatch [] rhs]
sigFun = const Nothing
pragFun = mkPragFun [] (unitBag bind)
-- perform type inference (including generalisation)
; (binds, [id'], _) <- tcPolyInfer False True sigFun pragFun NonRecursive [bind]
-
+
; traceTc "tcVect inferred type" $ ppr (varType id')
; traceTc "tcVect bindings" $ ppr binds
-
+
-- add all bindings, including the type variable and dictionary bindings produced by type
-- generalisation to the right-hand side of the vectorisation declaration
; let [AbsBinds tvs evs _ evBinds actualBinds] = (map unLoc . bagToList) binds
; let [bind'] = bagToList actualBinds
- MatchGroup
+ MatchGroup
[L _ (Match _ _ (GRHSs [L _ (GRHS _ rhs')] _))]
_ = (fun_matches . unLoc) bind'
rhsWrapped = mkHsLams tvs evs (mkHsDictLet evBinds rhs')
-
+
-- We return the type-checked 'Id', to propagate the inferred signature
-- to the vectoriser - see "Note [Typechecked vectorisation pragmas]" in HsDecls
; return $ HsVect (L loc id') (Just rhsWrapped)
@@ -990,7 +1000,7 @@ scalarTyConMustBeNullary = ptext (sLit "VECTORISE SCALAR type constructor must b
--------------
-- If typechecking the binds fails, then return with each
--- signature-less binder given type (forall a.a), to minimise
+-- signature-less binder given type (forall a.a), to minimise
-- subsequent error messages
recoveryCode :: [Name] -> TcSigFun -> TcM (LHsBinds TcId, [Id], TopLevelFlag)
recoveryCode binder_names sig_fn
@@ -999,7 +1009,7 @@ recoveryCode binder_names sig_fn
; return (emptyBag, poly_ids, if all is_closed poly_ids
then TopLevel else NotTopLevel) }
where
- mk_dummy name
+ mk_dummy name
| isJust (sig_fn name) = tcLookupId name -- Had signature; look it up
| otherwise = return (mkLocalId name forall_a_a) -- No signature
@@ -1021,7 +1031,7 @@ But SPECIALISE INLINE *can* make sense for GADTS:
ArrPair :: !Int -> Arr e1 -> Arr e2 -> Arr (e1, e2)
(!:) :: Arr e -> Int -> e
- {-# SPECIALISE INLINE (!:) :: Arr Int -> Int -> Int #-}
+ {-# SPECIALISE INLINE (!:) :: Arr Int -> Int -> Int #-}
{-# SPECIALISE INLINE (!:) :: Arr (a, b) -> Int -> (a, b) #-}
(ArrInt _ ba) !: (I# i) = I# (indexIntArray# ba i)
(ArrPair _ a1 a2) !: i = (a1 !: i, a2 !: i)
@@ -1046,7 +1056,7 @@ The rule for typing pattern bindings is this:
..sigs..
p = e
-where 'p' binds v1..vn, and 'e' may mention v1..vn,
+where 'p' binds v1..vn, and 'e' may mention v1..vn,
typechecks exactly like
..sigs..
@@ -1055,7 +1065,7 @@ typechecks exactly like
..
vn = case x of p -> vn
-Note that
+Note that
(f :: forall a. a -> a) = id
should not typecheck because
case id of { (f :: forall a. a->a) -> f }
@@ -1065,14 +1075,14 @@ will not typecheck.
tcMonoBinds :: RecFlag -- Whether the binding is recursive for typechecking purposes
-- i.e. the binders are mentioned in their RHSs, and
-- we are not rescued by a type signature
- -> TcSigFun -> LetBndrSpec
+ -> TcSigFun -> LetBndrSpec
-> [LHsBind Name]
-> TcM (LHsBinds TcId, [MonoBindInfo])
tcMonoBinds is_rec sig_fn no_gen
[ L b_loc (FunBind { fun_id = L nm_loc name, fun_infix = inf,
fun_matches = matches, bind_fvs = fvs })]
- -- Single function binding,
+ -- Single function binding,
| NonRecursive <- is_rec -- ...binder isn't mentioned in RHS
, Nothing <- sig_fn name -- ...with no type signature
= -- In this very special case we infer the type of the
@@ -1084,8 +1094,8 @@ tcMonoBinds is_rec sig_fn no_gen
do { rhs_ty <- newFlexiTyVarTy openTypeKind
; mono_id <- newNoSigLetBndr no_gen name rhs_ty
; (co_fn, matches') <- tcExtendIdBndrs [TcIdBndr mono_id NotTopLevel] $
- -- We extend the error context even for a non-recursive
- -- function so that in type error messages we show the
+ -- We extend the error context even for a non-recursive
+ -- function so that in type error messages we show the
-- type of the thing whose rhs we are type checking
tcMatchesFun name inf matches rhs_ty
@@ -1100,12 +1110,12 @@ tcMonoBinds _ sig_fn no_gen binds
-- Bring the monomorphic Ids, into scope for the RHSs
; let mono_info = getMonoBindInfo tc_binds
rhs_id_env = [(name,mono_id) | (name, Nothing, mono_id) <- mono_info]
- -- A monomorphic binding for each term variable that lacks
+ -- A monomorphic binding for each term variable that lacks
-- a type sig. (Ones with a sig are already in scope.)
- ; traceTc "tcMonoBinds" $ vcat [ ppr n <+> ppr id <+> ppr (idType id)
+ ; traceTc "tcMonoBinds" $ vcat [ ppr n <+> ppr id <+> ppr (idType id)
| (n,id) <- rhs_id_env]
- ; binds' <- tcExtendIdEnv2 rhs_id_env $
+ ; binds' <- tcExtendIdEnv2 rhs_id_env $
mapM (wrapLocM tcRhs) tc_binds
; return (listToBag binds', mono_info) }
@@ -1115,7 +1125,7 @@ tcMonoBinds _ sig_fn no_gen binds
-- if there's a signature for it, use the instantiated signature type
-- otherwise invent a type variable
-- You see that quite directly in the FunBind case.
---
+--
-- But there's a complication for pattern bindings:
-- data T = MkT (forall a. a->a)
-- MkT f = e
@@ -1126,7 +1136,7 @@ tcMonoBinds _ sig_fn no_gen binds
-- it; hence the TcMonoBind data type in which the LHS is done but the RHS isn't
data TcMonoBind -- Half completed; LHS done, RHS not done
- = TcFunBind MonoBindInfo SrcSpan Bool (MatchGroup Name (LHsExpr Name))
+ = TcFunBind MonoBindInfo SrcSpan Bool (MatchGroup Name (LHsExpr Name))
| TcPatBind [MonoBindInfo] (LPat TcId) (GRHSs Name (LHsExpr Name)) TcSigmaType
type MonoBindInfo = (Name, Maybe TcSigInfo, TcId)
@@ -1176,11 +1186,11 @@ tcRhs (TcFunBind (_,_,mono_id) loc inf matches)
= tcExtendIdBndrs [TcIdBndr mono_id NotTopLevel] $
-- NotTopLevel: it's a monomorphic binding
do { traceTc "tcRhs: fun bind" (ppr mono_id $$ ppr (idType mono_id))
- ; (co_fn, matches') <- tcMatchesFun (idName mono_id) inf
+ ; (co_fn, matches') <- tcMatchesFun (idName mono_id) inf
matches (idType mono_id)
; return (FunBind { fun_id = L loc mono_id, fun_infix = inf
, fun_matches = matches'
- , fun_co_fn = co_fn
+ , fun_co_fn = co_fn
, bind_fvs = placeHolderNamesTc
, fun_tick = Nothing }) }
@@ -1190,7 +1200,7 @@ tcRhs (TcPatBind infos pat' grhss pat_ty)
do { traceTc "tcRhs: pat bind" (ppr pat' $$ ppr pat_ty)
; grhss' <- addErrCtxt (patMonoBindsCtxt pat' grhss) $
tcGRHSsPat grhss pat_ty
- ; return (PatBind { pat_lhs = pat', pat_rhs = grhss', pat_rhs_ty = pat_ty
+ ; return (PatBind { pat_lhs = pat', pat_rhs = grhss', pat_rhs_ty = pat_ty
, bind_fvs = placeHolderNamesTc
, pat_ticks = (Nothing,[]) }) }
@@ -1231,7 +1241,7 @@ into scope for any explicitly forall-quantified type variables:
f x = e
Then 'a' is in scope inside 'e'.
-However, we do *not* support this
+However, we do *not* support this
- For pattern bindings e.g
f :: forall a. a->a
(f,g) = e
@@ -1244,7 +1254,7 @@ variable is set True when we are typechecking a single function
binding; and False for pattern bindings and a group of several
function bindings.
-Reason: in the latter cases, the "skolems" can be unified together,
+Reason: in the latter cases, the "skolems" can be unified together,
so they aren't properly rigid in the type-refinement sense.
NB: unless we are doing H98, each function with a sig will be done
separately, even if it's mutually recursive, so use_skols will be True
@@ -1267,7 +1277,7 @@ Note [Instantiate sig with fresh variables]
It's vital to instantiate a type signature with fresh variables.
For example:
type T = forall a. [a] -> [a]
- f :: T;
+ f :: T;
f = g where { g :: T; g = <rhs> }
We must not use the same 'a' from the defn of T at both places!!
@@ -1286,7 +1296,7 @@ If a type signaure is wrong, fail immediately:
to the ambiguity error.
ToDo: this means we fall over if any type sig
-is wrong (eg at the top level of the module),
+is wrong (eg at the top level of the module),
which is over-conservative
\begin{code}
@@ -1295,17 +1305,41 @@ tcTySigs hs_sigs
= checkNoErrs $ -- See Note [Fail eagerly on bad signatures]
do { ty_sigs_s<- mapAndRecoverM tcTySig hs_sigs
; let ty_sigs = concat ty_sigs_s
- env = mkNameEnv [(idName (sig_id sig), sig) | sig <- ty_sigs]
- ; return (map sig_id ty_sigs, lookupNameEnv env) }
+ poly_ids = [id | TcSigInfo{ sig_id = id } <- ty_sigs]
+ env = mkNameEnv [(getName sig, sig) | sig <- ty_sigs]
+ ; return (poly_ids, lookupNameEnv env) }
tcTySig :: LSig Name -> TcM [TcSigInfo]
tcTySig (L loc (IdSig id))
= do { sig <- instTcTySigFromId loc id
; return [sig] }
tcTySig (L loc (TypeSig names@(L _ name1 : _) hs_ty))
- = setSrcSpan loc $
+ = setSrcSpan loc $
do { sigma_ty <- tcHsSigType (FunSigCtxt name1) hs_ty
; mapM (instTcTySig hs_ty sigma_ty) (map unLoc names) }
+tcTySig (L loc (PatSynSig (L _ name) (_, qtvs) prov req ty))
+ = setSrcSpan loc $
+ do { traceTc "tcTySig {" $ ppr name $$ ppr qtvs $$ ppr prov $$ ppr req $$ ppr ty
+ ; let ctxt = FunSigCtxt name
+ ; tcHsTyVarBndrs qtvs $ \ qtvs' -> do
+ { ty' <- tcHsSigType ctxt ty
+ ; req' <- tcHsContext req
+ ; prov' <- tcHsContext prov
+
+ ; qtvs' <- mapM zonkQuantifiedTyVar qtvs'
+
+ ; let (_, pat_ty) = splitFunTys ty'
+ univ_set = tyVarsOfType pat_ty
+ (univ_tvs, ex_tvs) = partition (`elemVarSet` univ_set) qtvs'
+
+ ; traceTc "tcTySig }" $ ppr (ex_tvs, prov') $$ ppr (univ_tvs, req') $$ ppr ty'
+ ; let tpsi = TPSI{ patsig_name = name,
+ patsig_tau = ty',
+ patsig_ex = ex_tvs,
+ patsig_univ = univ_tvs,
+ patsig_prov = prov',
+ patsig_req = req' }
+ ; return [TcPatSynInfo tpsi] }}
tcTySig _ = return []
instTcTySigFromId :: SrcSpan -> Id -> TcM TcSigInfo
@@ -1486,12 +1520,12 @@ unliftedMustBeBang binds
polyBindErr :: [LHsBind Name] -> SDoc
polyBindErr binds
= hang (ptext (sLit "You can't mix polymorphic and unlifted bindings"))
- 2 (vcat [vcat (map ppr binds),
+ 2 (vcat [vcat (map ppr binds),
ptext (sLit "Probable fix: use a bang pattern")])
strictBindErr :: String -> Bool -> [LHsBind Name] -> SDoc
strictBindErr flavour unlifted_bndrs binds
- = hang (text flavour <+> msg <+> ptext (sLit "aren't allowed:"))
+ = hang (text flavour <+> msg <+> ptext (sLit "aren't allowed:"))
2 (vcat (map ppr binds))
where
msg | unlifted_bndrs = ptext (sLit "bindings for unlifted types")
@@ -1509,7 +1543,7 @@ Note [Binding scoped type variables]
\begin{code}
--- This one is called on LHS, when pat and grhss are both Name
+-- This one is called on LHS, when pat and grhss are both Name
-- and on RHS, when pat is TcId and grhss is still Name
patMonoBindsCtxt :: (OutputableBndr id, Outputable body) => LPat id -> GRHSs Name body -> SDoc
patMonoBindsCtxt pat grhss
diff --git a/compiler/typecheck/TcClassDcl.lhs b/compiler/typecheck/TcClassDcl.lhs
index 29d47b42d8..4e45d11091 100644
--- a/compiler/typecheck/TcClassDcl.lhs
+++ b/compiler/typecheck/TcClassDcl.lhs
@@ -238,7 +238,9 @@ tcInstanceMethodBody :: SkolemInfo -> [TcTyVar] -> [EvVar]
tcInstanceMethodBody skol_info tyvars dfun_ev_vars
meth_id local_meth_sig
specs (L loc bind)
- = do { let local_meth_id = sig_id local_meth_sig
+ = do { let local_meth_id = case local_meth_sig of
+ TcSigInfo{ sig_id = meth_id } -> meth_id
+ _ -> pprPanic "tcInstanceMethodBody" (ppr local_meth_sig)
lm_bind = L loc (bind { fun_id = L loc (idName local_meth_id) })
-- Substitute the local_meth_name for the binder
-- NB: the binding is always a FunBind
diff --git a/compiler/typecheck/TcPat.lhs b/compiler/typecheck/TcPat.lhs
index 6fdbc5214c..b18ab7e148 100644
--- a/compiler/typecheck/TcPat.lhs
+++ b/compiler/typecheck/TcPat.lhs
@@ -9,7 +9,8 @@ TcPat: Typechecking patterns
{-# LANGUAGE CPP, RankNTypes #-}
module TcPat ( tcLetPat, TcSigFun, TcPragFun
- , TcSigInfo(..), findScopedTyVars
+ , TcSigInfo(..), TcPatSynInfo(..)
+ , findScopedTyVars
, LetBndrSpec(..), addInlinePrags, warnPrags
, tcPat, tcPats, newNoSigLetBndr
, addDataConStupidTheta, badFieldCon, polyPatSig ) where
@@ -152,6 +153,17 @@ data TcSigInfo
sig_loc :: SrcSpan -- The location of the signature
}
+ | TcPatSynInfo TcPatSynInfo
+
+data TcPatSynInfo
+ = TPSI {
+ patsig_name :: Name,
+ patsig_tau :: TcSigmaType,
+ patsig_ex :: [TcTyVar],
+ patsig_prov :: TcThetaType,
+ patsig_univ :: [TcTyVar],
+ patsig_req :: TcThetaType
+ }
findScopedTyVars -- See Note [Binding scoped type variables]
:: LHsType Name -- The HsType
@@ -171,10 +183,19 @@ findScopedTyVars hs_ty sig_ty inst_tvs
scoped_names = mkNameSet (hsExplicitTvs hs_ty)
(sig_tvs,_) = tcSplitForAllTys sig_ty
+instance NamedThing TcSigInfo where
+ getName TcSigInfo{ sig_id = id } = idName id
+ getName (TcPatSynInfo tpsi) = patsig_name tpsi
+
instance Outputable TcSigInfo where
ppr (TcSigInfo { sig_id = id, sig_tvs = tyvars, sig_theta = theta, sig_tau = tau})
= ppr id <+> dcolon <+> vcat [ pprSigmaType (mkSigmaTy (map snd tyvars) theta tau)
, ppr (map fst tyvars) ]
+ ppr (TcPatSynInfo tpsi) = text "TcPatSynInfo" <+> ppr tpsi
+
+instance Outputable TcPatSynInfo where
+ ppr (TPSI{ patsig_name = name}) = ppr name
+
\end{code}
Note [Binding scoped type variables]
diff --git a/compiler/typecheck/TcPatSyn.lhs b/compiler/typecheck/TcPatSyn.lhs
index d6f6817cce..a2731ca2e8 100644
--- a/compiler/typecheck/TcPatSyn.lhs
+++ b/compiler/typecheck/TcPatSyn.lhs
@@ -7,7 +7,7 @@
\begin{code}
{-# LANGUAGE CPP #-}
-module TcPatSyn (tcPatSynDecl, mkPatSynWrapperId, tcPatSynWorker) where
+module TcPatSyn (tcInferPatSynDecl, tcCheckPatSynDecl, mkPatSynWrapperId, tcPatSynWorker) where
import HsSyn
import TcPat
@@ -28,32 +28,38 @@ import Id
import TcBinds
import BasicTypes
import TcSimplify
+import TcUnify
import TcType
+import TcEvidence
+import BuildTyCl
import VarSet
import MkId
+import VarEnv
+import Inst
#if __GLASGOW_HASKELL__ < 709
import Data.Monoid
#endif
import Bag
-import TcEvidence
-import BuildTyCl
+import Util
import Data.Maybe
+import Control.Monad (forM)
#include "HsVersions.h"
\end{code}
\begin{code}
-tcPatSynDecl :: PatSynBind Name Name
- -> TcM (PatSyn, LHsBinds Id)
-tcPatSynDecl PSB{ psb_id = lname@(L _ name), psb_args = details,
- psb_def = lpat, psb_dir = dir }
- = do { traceTc "tcPatSynDecl {" $ ppr name $$ ppr lpat
+tcInferPatSynDecl :: PatSynBind Name Name
+ -> TcM (PatSyn, LHsBinds Id)
+tcInferPatSynDecl PSB{ psb_id = lname@(L loc name), psb_args = details,
+ psb_def = lpat, psb_dir = dir }
+ = setSrcSpan loc $
+ do { traceTc "tcInferPatSynDecl {" $ ppr name
; tcCheckPatSynPat lpat
; let (arg_names, is_infix) = case details of
PrefixPatSyn names -> (map unLoc names, False)
InfixPatSyn name1 name2 -> (map unLoc [name1, name2], True)
- ; (((lpat', (args, pat_ty)), untch), wanted)
+ ; (((lpat', (args, pat_ty)), untch), wanted)
<- captureConstraints $
captureUntouchables $
do { pat_ty <- newFlexiTyVarTy openTypeKind
@@ -63,7 +69,6 @@ tcPatSynDecl PSB{ psb_id = lname@(L _ name), psb_args = details,
; let named_taus = (name, pat_ty) : map (\arg -> (getName arg, varType arg)) args
- ; traceTc "tcPatSynDecl::wanted" (ppr named_taus $$ ppr wanted)
; (qtvs, req_dicts, _mr_bites, ev_binds) <- simplifyInfer untch False named_taus wanted
; (ex_vars, prov_dicts) <- tcCollectEx lpat'
@@ -74,76 +79,163 @@ tcPatSynDecl PSB{ psb_id = lname@(L _ name), psb_args = details,
; univ_tvs <- mapM zonkQuantifiedTyVar univ_tvs
; ex_tvs <- mapM zonkQuantifiedTyVar ex_tvs
+
; prov_theta <- zonkTcThetaType prov_theta
; req_theta <- zonkTcThetaType req_theta
+
; pat_ty <- zonkTcType pat_ty
; args <- mapM zonkId args
- ; let arg_tys = map varType args
-
- ; traceTc "tcPatSynDecl: ex" (ppr ex_tvs $$
- ppr prov_theta $$
- ppr prov_dicts)
- ; traceTc "tcPatSynDecl: univ" (ppr univ_tvs $$
- ppr req_theta $$
- ppr req_dicts $$
- ppr ev_binds)
-
- ; let qtvs = univ_tvs ++ ex_tvs
- ; let theta = req_theta ++ prov_theta
-
- ; traceTc "tcPatSynDecl: type" (ppr name $$
- ppr univ_tvs $$
- ppr (map varType args) $$
- ppr pat_ty)
-
- ; (matcher_id, matcher_bind) <- tcPatSynMatcher lname lpat' args
- univ_tvs ex_tvs
- ev_binds
- prov_dicts req_dicts
- prov_theta req_theta
+
+ ; traceTc "tcInferPatSynDecl }" $ ppr name
+ ; tc_patsyn_finish lname dir is_infix lpat'
+ (univ_tvs, req_theta, ev_binds, req_dicts)
+ (ex_tvs, map mkTyVarTy ex_tvs, prov_theta, emptyTcEvBinds, prov_dicts)
+ (zip args $ repeat idHsWrapper)
+ pat_ty }
+
+tcCheckPatSynDecl :: PatSynBind Name Name
+ -> TcPatSynInfo
+ -> TcM (PatSyn, LHsBinds Id)
+tcCheckPatSynDecl PSB{ psb_id = lname@(L loc name), psb_args = details,
+ psb_def = lpat, psb_dir = dir }
+ TPSI{ patsig_tau = tau,
+ patsig_ex = ex_tvs, patsig_univ = univ_tvs,
+ patsig_prov = prov_theta, patsig_req = req_theta }
+ = setSrcSpan loc $
+ do { traceTc "tcCheckPatSynDecl" $
+ ppr (ex_tvs, prov_theta) $$
+ ppr (univ_tvs, req_theta) $$
+ ppr arg_tys $$
+ ppr tau
+ ; tcCheckPatSynPat lpat
+
+ ; req_dicts <- newEvVars req_theta
+
+ -- TODO: find a better SkolInfo
+ ; let skol_info = SigSkol (FunSigCtxt name) (mkFunTys arg_tys pat_ty)
+
+ ; let (arg_names, is_infix) = case details of
+ PrefixPatSyn names -> (map unLoc names, False)
+ InfixPatSyn name1 name2 -> (map unLoc [name1, name2], True)
+
+ ; let ty_arity = length arg_tys
+ ; checkTc (length arg_names == ty_arity)
+ (wrongNumberOfParmsErr ty_arity)
+
+ -- Typecheck the pattern against pat_ty, then unify the type of args
+ -- against arg_tys, with ex_tvs changed to SigTyVars.
+ -- We get out of this:
+ -- * The evidence bindings for the requested theta: req_ev_binds
+ -- * The typechecked pattern: lpat'
+ -- * The arguments, type-coerced to the SigTyVars: wrapped_args
+ -- * The instantiation of ex_tvs to pass to the success continuation: ex_tys
+ -- * The provided theta substituted with the SigTyVars: prov_theta'
+ ; (req_ev_binds, (lpat', (ex_tys, prov_theta', wrapped_args))) <-
+ checkConstraints skol_info univ_tvs req_dicts $
+ tcPat PatSyn lpat pat_ty $ do
+ { ex_sigtvs <- mapM (\tv -> newSigTyVar (getName tv) (tyVarKind tv)) ex_tvs
+ ; let subst = mkTvSubst (mkInScopeSet (zipVarEnv ex_sigtvs ex_sigtvs)) $
+ zipTyEnv ex_tvs (map mkTyVarTy ex_sigtvs)
+ ; let ex_tys = substTys subst $ map mkTyVarTy ex_tvs
+ prov_theta' = substTheta subst prov_theta
+ ; wrapped_args <- forM (zipEqual "tcCheckPatSynDecl" arg_names arg_tys) $ \(arg_name, arg_ty) -> do
+ { arg <- tcLookupId arg_name
+ ; let arg_ty' = substTy subst arg_ty
+ ; coi <- unifyType (varType arg) arg_ty'
+ ; return (setVarType arg arg_ty, coToHsWrapper coi) }
+ ; return (ex_tys, prov_theta', wrapped_args) }
+
+ ; (ex_vars_rhs, prov_dicts_rhs) <- tcCollectEx lpat'
+ ; let ex_tvs_rhs = varSetElems ex_vars_rhs
+
+ -- Check that prov_theta' can be satisfied with the dicts from the pattern
+ ; (prov_ev_binds, prov_dicts) <-
+ checkConstraints skol_info ex_tvs_rhs prov_dicts_rhs $ do
+ { let origin = PatOrigin -- TODO
+ ; emitWanteds origin prov_theta' }
+
+ ; traceTc "tcCheckPatSynDecl }" $ ppr name
+ ; tc_patsyn_finish lname dir is_infix lpat'
+ (univ_tvs, req_theta, req_ev_binds, req_dicts)
+ (ex_tvs, ex_tys, prov_theta, prov_ev_binds, prov_dicts)
+ wrapped_args
+ pat_ty }
+ where
+ (arg_tys, pat_ty) = tcSplitFunTys tau
+
+wrongNumberOfParmsErr :: Arity -> SDoc
+wrongNumberOfParmsErr ty_arity
+ = ptext (sLit "Number of pattern synonym arguments doesn't match type; expected")
+ <+> ppr ty_arity
+
+tc_patsyn_finish :: Located Name
+ -> HsPatSynDir Name
+ -> Bool
+ -> LPat Id
+ -> ([TcTyVar], [PredType], TcEvBinds, [EvVar])
+ -> ([TcTyVar], [TcType], [PredType], TcEvBinds, [EvVar])
+ -> [(Var, HsWrapper)]
+ -> TcType
+ -> TcM (PatSyn, LHsBinds Id)
+tc_patsyn_finish lname dir is_infix lpat'
+ (univ_tvs, req_theta, req_ev_binds, req_dicts)
+ (ex_tvs, subst, prov_theta, prov_ev_binds, prov_dicts)
+ wrapped_args
+ pat_ty
+ = do { (matcher_id, matcher_bind) <- tcPatSynMatcher lname lpat'
+ (univ_tvs, req_theta, req_ev_binds, req_dicts)
+ (ex_tvs, subst, prov_theta, prov_ev_binds, prov_dicts)
+ wrapped_args
pat_ty
; wrapper_ids <- if isBidirectional dir
- then fmap Just $ mkPatSynWrapperIds lname
- qtvs theta
- arg_tys pat_ty
+ then fmap Just $ mkPatSynWrapperIds lname qtvs theta arg_tys pat_ty
else return Nothing
- ; traceTc "tcPatSynDecl }" $ ppr name
- ; let patSyn = mkPatSyn name is_infix
+ ; let patSyn = mkPatSyn (unLoc lname) is_infix
(univ_tvs, req_theta)
(ex_tvs, prov_theta)
arg_tys
pat_ty
matcher_id wrapper_ids
; return (patSyn, matcher_bind) }
-
+ where
+ qtvs = univ_tvs ++ ex_tvs
+ theta = prov_theta ++ req_theta
+ arg_tys = map (varType . fst) wrapped_args
\end{code}
\begin{code}
tcPatSynMatcher :: Located Name
-> LPat Id
- -> [Var]
- -> [TcTyVar] -> [TcTyVar]
- -> TcEvBinds
- -> [EvVar] -> [EvVar]
- -> ThetaType -> ThetaType
+ -> ([TcTyVar], ThetaType, TcEvBinds, [EvVar])
+ -> ([TcTyVar], [TcType], ThetaType, TcEvBinds, [EvVar])
+ -> [(Var, HsWrapper)]
-> TcType
-> TcM (Id, LHsBinds Id)
-- See Note [Matchers and wrappers for pattern synonyms] in PatSyn
-tcPatSynMatcher (L loc name) lpat args univ_tvs ex_tvs ev_binds prov_dicts req_dicts prov_theta req_theta pat_ty
+tcPatSynMatcher (L loc name) lpat
+ (univ_tvs, req_theta, req_ev_binds, req_dicts)
+ (ex_tvs, ex_tys, prov_theta, prov_ev_binds, prov_dicts)
+ wrapped_args pat_ty
= do { res_tv <- do
{ uniq <- newUnique
; let tv_name = mkInternalName uniq (mkTyVarOcc "r") loc
; return $ mkTcTyVar tv_name openTypeKind (SkolemTv False) }
- ; matcher_name <- newImplicitBinder name mkMatcherOcc
; let res_ty = mkTyVarTy res_tv
- cont_args = if null args then [voidPrimId] else args
+
+ ; let (cont_arg_tys, cont_args)
+ | null wrapped_args = ([voidPrimTy], [nlHsVar voidPrimId])
+ | otherwise = unzip [ (varType arg, mkLHsWrap wrap $ nlHsVar arg)
+ | (arg, wrap) <- wrapped_args
+ ]
cont_ty = mkSigmaTy ex_tvs prov_theta $
- mkFunTys (map varType cont_args) res_ty
- fail_ty = mkFunTy voidPrimTy res_ty
+ mkFunTys cont_arg_tys res_ty
+ ; let fail_ty = mkFunTy voidPrimTy res_ty
+
+ ; matcher_name <- newImplicitBinder name mkMatcherOcc
; 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
@@ -153,8 +245,9 @@ tcPatSynMatcher (L loc name) lpat args univ_tvs ex_tvs ev_binds prov_dicts req_d
; scrutinee <- mkId "scrut" pat_ty
; cont <- mkId "cont" cont_ty
- ; let cont' = nlHsTyApps cont (map mkTyVarTy ex_tvs) $
- map nlHsVar (prov_dicts ++ cont_args)
+ ; let cont_dicts = map nlHsVar prov_dicts
+ ; let cont' = nlHsTyApps cont ex_tys $ cont_dicts ++ cont_args
+ ; cont' <- return $ mkLHsWrap (mkWpLet prov_ev_binds) cont'
; fail <- mkId "fail" fail_ty
; let fail' = nlHsApps fail [nlHsVar voidPrimId]
@@ -164,7 +257,7 @@ tcPatSynMatcher (L loc name) lpat args univ_tvs ex_tvs ev_binds prov_dicts req_d
then [mkSimpleHsAlt lpat cont']
else [mkSimpleHsAlt lpat cont',
mkSimpleHsAlt lwpat fail']
- body = mkLHsWrap (mkWpLet ev_binds) $
+ body = mkLHsWrap (mkWpLet req_ev_binds) $
L (getLoc lpat) $
HsCase (nlHsVar scrutinee) $
MG{ mg_alts = cases
diff --git a/compiler/typecheck/TcPatSyn.lhs-boot b/compiler/typecheck/TcPatSyn.lhs-boot
index 0e28caa6ca..d22d46f93f 100644
--- a/compiler/typecheck/TcPatSyn.lhs-boot
+++ b/compiler/typecheck/TcPatSyn.lhs-boot
@@ -6,9 +6,14 @@ import Id ( Id )
import HsSyn ( PatSynBind, LHsBinds )
import TcRnTypes ( TcM )
import PatSyn ( PatSyn )
+import TcPat ( TcPatSynInfo )
-tcPatSynDecl :: PatSynBind Name Name
- -> TcM (PatSyn, LHsBinds Id)
+tcInferPatSynDecl :: PatSynBind Name Name
+ -> TcM (PatSyn, LHsBinds Id)
+
+tcCheckPatSynDecl :: PatSynBind Name Name
+ -> TcPatSynInfo
+ -> TcM (PatSyn, LHsBinds Id)
tcPatSynWorker :: PatSynBind Name Name
-> TcM (LHsBinds Id)
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index edd1ccc277..51d7b731e4 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -1081,7 +1081,7 @@ would bring into scope the data constructor <literal>Just</literal> from the
it is assigned a <emphasis>pattern type</emphasis> of the form
</para>
<programlisting>
- pattern CProv => P t1 t2 ... tN :: CReq => t
+ pattern P :: CProv => CReq => t1 -> t2 -> ... -> tN -> t
</programlisting>
<para>
where <replaceable>CProv</replaceable> and
@@ -1114,7 +1114,7 @@ pattern ExNumPat x = MkT 42 x
</programlisting>
<para>
-the pattern type of <literal>ExNumPat</literal> is
+the inferred pattern type of <literal>ExNumPat</literal> is
</para>
<programlisting>
@@ -1146,6 +1146,17 @@ pattern (Show b) => ExNumPat b :: (Num a, Eq a) => T a
</programlisting>
</sect3>
+<para>
+ Pattern synonyms can also be given a type signature in the source
+ program, e.g.:
+</para>
+
+<programlisting>
+ -- Inferred type would be 'a -> [a]'
+ pattern SinglePair :: (a, a) -> [(a, a)]
+ pattern SinglePair x = [x]
+</programlisting>
+
<sect3><title>Matching of pattern synonyms</title>
<para>
diff --git a/testsuite/tests/ghci/scripts/T8776.stdout b/testsuite/tests/ghci/scripts/T8776.stdout
index 9c9e89ad94..5aea751e80 100644
--- a/testsuite/tests/ghci/scripts/T8776.stdout
+++ b/testsuite/tests/ghci/scripts/T8776.stdout
@@ -1 +1 @@
-pattern (Num t, Eq t1) => P :: (A t t1) -- Defined at T8776.hs:6:9
+pattern P :: (Num t, Eq t1) => A t t1 -- Defined at T8776.hs:6:9
diff --git a/testsuite/tests/patsyn/should_compile/T8584-1.hs b/testsuite/tests/patsyn/should_compile/T8584-1.hs
new file mode 100644
index 0000000000..d2b20f13e3
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8584-1.hs
@@ -0,0 +1,5 @@
+{-# LANGUAGE PatternSynonyms #-}
+module ShouldCompile where
+
+pattern Single :: a -> [a]
+pattern Single x = [x]
diff --git a/testsuite/tests/patsyn/should_compile/T8584-2.hs b/testsuite/tests/patsyn/should_compile/T8584-2.hs
new file mode 100644
index 0000000000..d267d39887
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8584-2.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE PatternSynonyms #-}
+module ShouldCompile where
+
+pattern Single :: () => (Show a) => a -> [a]
+pattern Single x = [x]
+
+f :: (Show a) => [a] -> a
+f (Single x) = x
diff --git a/testsuite/tests/patsyn/should_compile/T8584-3.hs b/testsuite/tests/patsyn/should_compile/T8584-3.hs
new file mode 100644
index 0000000000..d81340c4c8
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8584-3.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE PatternSynonyms #-}
+module ShouldCompile where
+
+pattern SinglePair :: (a, a) -> [(a, a)]
+pattern SinglePair x = [x]
+
+f :: (Show a) => [(a, a)] -> String
+f (SinglePair x) = show x
diff --git a/testsuite/tests/patsyn/should_compile/T8968-1.hs b/testsuite/tests/patsyn/should_compile/T8968-1.hs
new file mode 100644
index 0000000000..f41ed5352b
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8968-1.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE GADTs, KindSignatures, PatternSynonyms #-}
+module ShouldCompile where
+
+data X :: (* -> *) -> * -> * where
+ Y :: f a -> X f (Maybe a)
+
+pattern C :: a -> X Maybe (Maybe a)
+pattern C x = Y (Just x)
diff --git a/testsuite/tests/patsyn/should_compile/T8968-2.hs b/testsuite/tests/patsyn/should_compile/T8968-2.hs
new file mode 100644
index 0000000000..05453ec98e
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8968-2.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE GADTs, KindSignatures, PatternSynonyms #-}
+module ShouldCompile where
+
+data X :: (* -> *) -> * -> * where
+ Y :: (Show a) => f a -> X f (Maybe a)
+
+pattern C :: (Show (a, Bool)) => a -> X Maybe (Maybe (a, Bool))
+pattern C x = Y (Just (x, True))
diff --git a/testsuite/tests/patsyn/should_compile/T8968-3.hs b/testsuite/tests/patsyn/should_compile/T8968-3.hs
new file mode 100644
index 0000000000..adbae71a4f
--- /dev/null
+++ b/testsuite/tests/patsyn/should_compile/T8968-3.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE GADTs, KindSignatures, PatternSynonyms #-}
+module ShouldCompile where
+
+data T a b where
+ MkT :: a -> T a Bool
+
+pattern P :: T Bool b
+pattern P <- MkT True
+
+pattern D :: a -> T (Maybe a) Bool
+pattern D x = MkT (Just x)
diff --git a/testsuite/tests/patsyn/should_compile/all.T b/testsuite/tests/patsyn/should_compile/all.T
index 55e3b83302..6a51bf5e7d 100644
--- a/testsuite/tests/patsyn/should_compile/all.T
+++ b/testsuite/tests/patsyn/should_compile/all.T
@@ -12,3 +12,9 @@ test('T8966', normal, compile, [''])
test('T9023', normal, compile, [''])
test('unboxed-bind-bang', normal, compile, [''])
test('T9732', normal, compile, [''])
+test('T8584-1', normal, compile, [''])
+test('T8584-2', normal, compile, [''])
+test('T8584-3', normal, compile, [''])
+test('T8968-1', normal, compile, [''])
+test('T8968-2', normal, compile, [''])
+test('T8968-3', normal, compile, [''])
diff --git a/utils/haddock b/utils/haddock
-Subproject 9cdf19bad54a6cc4b322396fdd06f4c1ee045b2
+Subproject edd2a3be44656e763419679bb426a384d9e1a74