Add support for pattern synonym type signatures.
authorDr. ERDI Gergo <gergo@erdi.hu>
Thu, 20 Nov 2014 14:38:11 +0000 (22:38 +0800)
committerDr. ERDI Gergo <gergo@erdi.hu>
Thu, 20 Nov 2014 14:38:11 +0000 (22:38 +0800)
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)`.

The Haddock submodule is also updated to use this new syntax in generated docs.

22 files changed:
compiler/hsSyn/HsBinds.lhs
compiler/hsSyn/HsTypes.lhs
compiler/iface/IfaceSyn.lhs
compiler/iface/IfaceType.lhs
compiler/parser/Parser.y
compiler/parser/RdrHsSyn.hs
compiler/rename/RnBinds.lhs
compiler/typecheck/TcBinds.lhs
compiler/typecheck/TcClassDcl.lhs
compiler/typecheck/TcPat.lhs
compiler/typecheck/TcPatSyn.lhs
compiler/typecheck/TcPatSyn.lhs-boot
docs/users_guide/glasgow_exts.xml
testsuite/tests/ghci/scripts/T8776.stdout
testsuite/tests/patsyn/should_compile/T8584-1.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/T8584-2.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/T8584-3.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/T8968-1.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/T8968-2.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/T8968-3.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/all.T
utils/haddock

index 95ec98e..b345e88 100644 (file)
@@ -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)]
index 9bd5845..4a01948 100644 (file)
@@ -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)))
index c2b7c52..49d645d 100644 (file)
@@ -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 })
index aae61c4..223a25b 100644 (file)
@@ -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
index 6f6422f..eb528c3 100644 (file)
@@ -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 '#-}'
index 625c4dc..e945e43 100644 (file)
@@ -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
index c2489cb..80239e9 100644 (file)
@@ -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)
index c2af407..ec5f9d7 100644 (file)
@@ -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
index 29d47b4..4e45d11 100644 (file)
@@ -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
index 6fdbc52..b18ab7e 100644 (file)
@@ -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]
index d6f6817..a2731ca 100644 (file)
@@ -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
index 0e28caa..d22d46f 100644 (file)
@@ -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)
index edd1ccc..51d7b73 100644 (file)
@@ -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>
index 9c9e89a..5aea751 100644 (file)
@@ -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 (file)
index 0000000..d2b20f1
--- /dev/null
@@ -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 (file)
index 0000000..d267d39
--- /dev/null
@@ -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 (file)
index 0000000..d81340c
--- /dev/null
@@ -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 (file)
index 0000000..f41ed53
--- /dev/null
@@ -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 (file)
index 0000000..05453ec
--- /dev/null
@@ -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 (file)
index 0000000..adbae71
--- /dev/null
@@ -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)
index 55e3b83..6a51bf5 100644 (file)
@@ -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, [''])
index 9cdf19b..bf80e2f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9cdf19bad54a6cc4b322396fdd06f4c1ee045b22
+Subproject commit bf80e2f594777c0c32fae092454bff0c13ae6181