diff options
author | Dr. ERDI Gergo <gergo@erdi.hu> | 2014-11-20 22:38:11 +0800 |
---|---|---|
committer | Dr. ERDI Gergo <gergo@erdi.hu> | 2014-11-20 22:38:11 +0800 |
commit | cce6318e8fdb086a8501a0c81ae1ee02eed67835 (patch) | |
tree | f9257e7f86fa47c73e22951fdb1471310d252504 /compiler | |
parent | 3b81309c057fc216afa053d195aaa85ee3a1ba9e (diff) | |
download | haskell-cce6318e8fdb086a8501a0c81ae1ee02eed67835.tar.gz |
Add support for pattern synonym type signatures.
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.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/hsSyn/HsBinds.lhs | 51 | ||||
-rw-r--r-- | compiler/hsSyn/HsTypes.lhs | 16 | ||||
-rw-r--r-- | compiler/iface/IfaceSyn.lhs | 25 | ||||
-rw-r--r-- | compiler/iface/IfaceType.lhs | 15 | ||||
-rw-r--r-- | compiler/parser/Parser.y | 51 | ||||
-rw-r--r-- | compiler/parser/RdrHsSyn.hs | 27 | ||||
-rw-r--r-- | compiler/rename/RnBinds.lhs | 42 | ||||
-rw-r--r-- | compiler/typecheck/TcBinds.lhs | 214 | ||||
-rw-r--r-- | compiler/typecheck/TcClassDcl.lhs | 4 | ||||
-rw-r--r-- | compiler/typecheck/TcPat.lhs | 23 | ||||
-rw-r--r-- | compiler/typecheck/TcPatSyn.lhs | 197 | ||||
-rw-r--r-- | compiler/typecheck/TcPatSyn.lhs-boot | 9 |
12 files changed, 415 insertions, 259 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) |