diff options
author | Dominik Bollmann <bollmann@seas.upenn.edu> | 2016-05-11 15:55:13 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-05-12 15:39:30 +0200 |
commit | c079de3c43704ea88f592e441389e520313e30ad (patch) | |
tree | a3d85f9118ec73abdc7058b8c3123afc18bf9360 | |
parent | e21728736d2ca0d65da9e84c18a12c2f29c116ee (diff) | |
download | haskell-c079de3c43704ea88f592e441389e520313e30ad.tar.gz |
Add TH support for pattern synonyms (fixes #8761)
This commit adds Template Haskell support for pattern synonyms as
requested by trac ticket #8761.
Test Plan: ./validate
Reviewers: thomie, jstolarek, osa1, RyanGlScott, mpickering, austin,
goldfire, bgamari
Reviewed By: goldfire, bgamari
Subscribers: rdragon
Differential Revision: https://phabricator.haskell.org/D1940
GHC Trac Issues: #8761
-rw-r--r-- | compiler/deSugar/DsMeta.hs | 129 | ||||
-rw-r--r-- | compiler/hsSyn/Convert.hs | 108 | ||||
-rw-r--r-- | compiler/hsSyn/HsTypes.hs | 25 | ||||
-rw-r--r-- | compiler/hsSyn/HsUtils.hs | 38 | ||||
-rw-r--r-- | compiler/prelude/THNames.hs | 174 | ||||
-rw-r--r-- | compiler/typecheck/TcSplice.hs | 21 | ||||
-rw-r--r-- | libraries/ghci/GHCi/TH/Binary.hs | 2 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH.hs | 12 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Lib.hs | 39 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Ppr.hs | 65 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/PprLib.hs | 2 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Syntax.hs | 92 | ||||
-rw-r--r-- | testsuite/tests/quotes/T8759a.stderr | 4 | ||||
-rw-r--r-- | testsuite/tests/quotes/all.T | 2 | ||||
-rw-r--r-- | testsuite/tests/th/T10019.stdout | 2 | ||||
-rw-r--r-- | testsuite/tests/th/T8759.stderr | 4 | ||||
-rw-r--r-- | testsuite/tests/th/T8761.hs | 111 | ||||
-rw-r--r-- | testsuite/tests/th/T8761.stderr | 158 | ||||
-rw-r--r-- | testsuite/tests/th/T9064.stderr | 5 | ||||
-rw-r--r-- | testsuite/tests/th/all.T | 4 |
20 files changed, 833 insertions, 164 deletions
diff --git a/compiler/deSugar/DsMeta.hs b/compiler/deSugar/DsMeta.hs index b00717e53a..370e310204 100644 --- a/compiler/deSugar/DsMeta.hs +++ b/compiler/deSugar/DsMeta.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP #-} +{-# LANGUAGE CPP, TypeFamilies #-} ----------------------------------------------------------------------------- -- @@ -119,8 +119,9 @@ repTopDs group@(HsGroup { hs_valds = valds , hs_ruleds = ruleds , hs_vects = vects , hs_docs = docs }) - = do { let { tv_bndrs = hsSigTvBinders valds - ; bndrs = tv_bndrs ++ hsGroupBinders group + = do { let { bndrs = hsSigTvBinders valds + ++ hsGroupBinders group + ++ hsPatSynSelectors valds ; instds = tyclds >>= group_instds } ; ss <- mkGenSyms bndrs ; @@ -197,7 +198,6 @@ hsSigTvBinders binds ValBindsIn _ sigs -> sigs ValBindsOut _ sigs -> sigs - {- Notes Note [Scoped type variables in bindings] @@ -700,7 +700,7 @@ rep_sigs' sigs = do { sigs1 <- mapM rep_sig sigs ; rep_sig :: LSig Name -> DsM [(SrcSpan, Core TH.DecQ)] rep_sig (L loc (TypeSig nms ty)) = mapM (rep_wc_ty_sig sigDName loc ty) nms -rep_sig (L _ (PatSynSig {})) = notHandled "Pattern type signatures" empty +rep_sig (L loc (PatSynSig nm ty)) = (:[]) <$> rep_patsyn_ty_sig loc ty nm rep_sig (L loc (ClassOpSig is_deflt nms ty)) | is_deflt = mapM (rep_ty_sig defaultSigDName loc ty) nms | otherwise = mapM (rep_ty_sig sigDName loc ty) nms @@ -708,7 +708,7 @@ rep_sig d@(L _ (IdSig {})) = pprPanic "rep_sig IdSig" (ppr d) rep_sig (L _ (FixSig {})) = return [] -- fixity sigs at top level rep_sig (L loc (InlineSig nm ispec)) = rep_inline nm ispec loc rep_sig (L loc (SpecSig nm tys ispec)) - = concatMapM (\t -> rep_specialise nm t ispec loc) tys + = concatMapM (\t -> rep_specialise nm t ispec loc) tys rep_sig (L loc (SpecInstSig _ ty)) = rep_specialiseInst ty loc rep_sig (L _ (MinimalSig {})) = notHandled "MINIMAL pragmas" empty @@ -720,6 +720,16 @@ rep_ty_sig mk_sig loc sig_ty nm ; sig <- repProto mk_sig nm1 ty1 ; return (loc, sig) } +rep_patsyn_ty_sig :: SrcSpan -> LHsSigType Name -> Located Name + -> DsM (SrcSpan, Core TH.DecQ) +-- represents a pattern synonym type signature; see NOTE [Pattern +-- synonym signatures and Template Haskell] +rep_patsyn_ty_sig loc sig_ty nm + = do { nm1 <- lookupLOcc nm + ; ty1 <- repHsPatSynSigType sig_ty + ; sig <- repProto patSynSigDName nm1 ty1 + ; return (loc, sig) } + rep_wc_ty_sig :: Name -> SrcSpan -> LHsSigWcType Name -> Located Name -> DsM (SrcSpan, Core TH.DecQ) -- We must special-case the top-level explicit for-all of a TypeSig @@ -889,17 +899,32 @@ repHsSigType (HsIB { hsib_vars = vars then return th_ty else repTForall th_tvs th_ctxt th_ty } +repHsPatSynSigType :: LHsSigType Name -> DsM (Core TH.TypeQ) +repHsPatSynSigType (HsIB { hsib_vars = implicit_tvs + , hsib_body = body }) + = addTyVarBinds (newTvs (impls ++ univs)) $ \th_univs -> + addTyVarBinds (newTvs exis) $ \th_exis -> + do { th_reqs <- repLContext reqs + ; th_provs <- repLContext provs + ; th_ty <- repLTy ty + ; repTForall th_univs th_reqs =<< (repTForall th_exis th_provs th_ty) } + where + impls = map (noLoc . UserTyVar . noLoc) implicit_tvs + newTvs tvs = HsQTvs + { hsq_implicit = [] + , hsq_explicit = tvs + , hsq_dependent = emptyNameSet } + (univs, reqs, exis, provs, ty) = splitLHsPatSynTy body + repHsSigWcType :: LHsSigWcType Name -> DsM (Core TH.TypeQ) repHsSigWcType ib_ty@(HsIB { hsib_body = sig1 }) = repHsSigType (ib_ty { hsib_body = hswc_body sig1 }) -- yield the representation of a list of types --- repLTys :: [LHsType Name] -> DsM [Core TH.TypeQ] repLTys tys = mapM repLTy tys -- represent a type --- repLTy :: LHsType Name -> DsM (Core TH.TypeQ) repLTy (L _ ty) = repTy ty @@ -1073,11 +1098,11 @@ repE :: HsExpr Name -> DsM (Core TH.ExpQ) repE (HsVar (L _ x)) = do { mb_val <- dsLookupMetaEnv x ; case mb_val of - Nothing -> do { str <- globalVar x - ; repVarOrCon x str } + Nothing -> do { str <- globalVar x + ; repVarOrCon x str } Just (DsBound y) -> repVarOrCon x (coreVar y) Just (DsSplice e) -> do { e' <- dsExpr e - ; return (MkC e') } } + ; return (MkC e') } } repE e@(HsIPVar _) = notHandled "Implicit parameters" (ppr e) repE e@(HsOverLabel _) = notHandled "Overloaded labels" (ppr e) @@ -1415,7 +1440,87 @@ rep_bind (L _ (VarBind { var_id = v, var_rhs = e})) rep_bind (L _ (AbsBinds {})) = panic "rep_bind: AbsBinds" rep_bind (L _ (AbsBindsSig {})) = panic "rep_bind: AbsBindsSig" -rep_bind (L _ dec@(PatSynBind {})) = notHandled "pattern synonyms" (ppr dec) +rep_bind (L loc (PatSynBind (PSB { psb_id = syn + , psb_fvs = _fvs + , psb_args = args + , psb_def = pat + , psb_dir = dir }))) + = do { syn' <- lookupLBinder syn + ; dir' <- repPatSynDir dir + ; ss <- mkGenArgSyms args + ; patSynD' <- addBinds ss ( + do { args' <- repPatSynArgs args + ; pat' <- repLP pat + ; repPatSynD syn' args' dir' pat' }) + ; patSynD'' <- wrapGenArgSyms args ss patSynD' + ; return (loc, patSynD'') } + where + mkGenArgSyms :: HsPatSynDetails (Located Name) -> DsM [GenSymBind] + -- for Record Pattern Synonyms we want to conflate the selector + -- and the pattern-only names in order to provide a nicer TH + -- API. Whereas inside GHC, record pattern synonym selectors and + -- their pattern-only bound right hand sides have different names, + -- we want to treat them the same in TH. This is the reason why we + -- need an adjusted mkGenArgSyms in the `RecordPatSyn` case below. + mkGenArgSyms (PrefixPatSyn args) = mkGenSyms (map unLoc args) + mkGenArgSyms (InfixPatSyn arg1 arg2) = mkGenSyms [unLoc arg1, unLoc arg2] + mkGenArgSyms (RecordPatSyn fields) + = do { let pats = map (unLoc . recordPatSynPatVar) fields + sels = map (unLoc . recordPatSynSelectorId) fields + ; ss <- mkGenSyms sels + ; return $ replaceNames (zip sels pats) ss } + + replaceNames selsPats genSyms + = [ (pat, id) | (sel, id) <- genSyms, (sel', pat) <- selsPats + , sel == sel' ] + + wrapGenArgSyms :: HsPatSynDetails (Located Name) + -> [GenSymBind] -> Core TH.DecQ -> DsM (Core TH.DecQ) + wrapGenArgSyms (RecordPatSyn _) _ dec = return dec + wrapGenArgSyms _ ss dec = wrapGenSyms ss dec + +repPatSynD :: Core TH.Name + -> Core TH.PatSynArgsQ + -> Core TH.PatSynDirQ + -> Core TH.PatQ + -> DsM (Core TH.DecQ) +repPatSynD (MkC syn) (MkC args) (MkC dir) (MkC pat) + = rep2 patSynDName [syn, args, dir, pat] + +repPatSynArgs :: HsPatSynDetails (Located Name) -> DsM (Core TH.PatSynArgsQ) +repPatSynArgs (PrefixPatSyn args) + = do { args' <- repList nameTyConName lookupLOcc args + ; repPrefixPatSynArgs args' } +repPatSynArgs (InfixPatSyn arg1 arg2) + = do { arg1' <- lookupLOcc arg1 + ; arg2' <- lookupLOcc arg2 + ; repInfixPatSynArgs arg1' arg2' } +repPatSynArgs (RecordPatSyn fields) + = do { sels' <- repList nameTyConName lookupLOcc sels + ; repRecordPatSynArgs sels' } + where sels = map recordPatSynSelectorId fields + +repPrefixPatSynArgs :: Core [TH.Name] -> DsM (Core TH.PatSynArgsQ) +repPrefixPatSynArgs (MkC nms) = rep2 prefixPatSynName [nms] + +repInfixPatSynArgs :: Core TH.Name -> Core TH.Name -> DsM (Core TH.PatSynArgsQ) +repInfixPatSynArgs (MkC nm1) (MkC nm2) = rep2 infixPatSynName [nm1, nm2] + +repRecordPatSynArgs :: Core [TH.Name] + -> DsM (Core TH.PatSynArgsQ) +repRecordPatSynArgs (MkC sels) = rep2 recordPatSynName [sels] + +repPatSynDir :: HsPatSynDir Name -> DsM (Core TH.PatSynDirQ) +repPatSynDir Unidirectional = rep2 unidirPatSynName [] +repPatSynDir ImplicitBidirectional = rep2 implBidirPatSynName [] +repPatSynDir (ExplicitBidirectional (MG { mg_alts = L _ clauses })) + = do { clauses' <- mapM repClauseTup clauses + ; repExplBidirPatSynDir (nonEmptyCoreList clauses') } + +repExplBidirPatSynDir :: Core [TH.ClauseQ] -> DsM (Core TH.PatSynDirQ) +repExplBidirPatSynDir (MkC cls) = rep2 explBidirPatSynName [cls] + + ----------------------------------------------------------------------------- -- Since everything in a Bind is mutually recursive we need rename all -- all the variables simultaneously. For example: diff --git a/compiler/hsSyn/Convert.hs b/compiler/hsSyn/Convert.hs index 9274725fe6..63904ed219 100644 --- a/compiler/hsSyn/Convert.hs +++ b/compiler/hsSyn/Convert.hs @@ -350,6 +350,33 @@ cvtDec (TH.DefaultSigD nm typ) = do { nm' <- vNameL nm ; ty' <- cvtType typ ; returnJustL $ Hs.SigD $ ClassOpSig True [nm'] (mkLHsSigType ty') } + +cvtDec (TH.PatSynD nm args dir pat) + = do { nm' <- cNameL nm + ; args' <- cvtArgs args + ; dir' <- cvtDir dir + ; pat' <- cvtPat pat + ; returnJustL $ Hs.ValD $ PatSynBind $ + PSB nm' placeHolderType args' pat' dir' } + where + cvtArgs (TH.PrefixPatSyn args) = Hs.PrefixPatSyn <$> mapM vNameL args + cvtArgs (TH.InfixPatSyn a1 a2) = Hs.InfixPatSyn <$> vNameL a1 <*> vNameL a2 + cvtArgs (TH.RecordPatSyn sels) + = do { sels' <- mapM vNameL sels + ; vars' <- mapM (vNameL . mkNameS . nameBase) sels + ; return $ Hs.RecordPatSyn $ zipWith RecordPatSynField sels' vars' } + + cvtDir Unidir = return Unidirectional + cvtDir ImplBidir = return ImplicitBidirectional + cvtDir (ExplBidir cls) = + do { ms <- mapM cvtClause cls + ; return $ ExplicitBidirectional $ mkMatchGroup FromSource ms } + +cvtDec (TH.PatSynSigD nm ty) + = do { nm' <- cNameL nm + ; ty' <- cvtPatSynSigTy ty + ; returnJustL $ Hs.SigD $ PatSynSig nm' (mkLHsSigType ty') } + ---------------- cvtTySynEqn :: Located RdrName -> TySynEqn -> CvtM (LTyFamInstEqn RdrName) cvtTySynEqn tc (TySynEqn lhs rhs) @@ -725,9 +752,9 @@ cvtl e = wrapL (cvt e) | overloadedLit l = do { l' <- cvtOverLit l; return $ HsOverLit l' } | otherwise = do { l' <- cvtLit l; return $ HsLit l' } cvt (AppE x@(LamE _ _) y) = do { x' <- cvtl x; y' <- cvtl y - ; return $ HsApp (mkLHsPar x') y' } + ; return $ HsApp (mkLHsPar x') y' } cvt (AppE x y) = do { x' <- cvtl x; y' <- cvtl y - ; return $ HsApp x' y' } + ; return $ HsApp x' y' } cvt (LamE ps e) = do { ps' <- cvtPats ps; e' <- cvtl e ; return $ HsLam (mkMatchGroup FromSource [mkSimpleMatch ps' e']) } cvt (LamCaseE ms) = do { ms' <- mapM cvtMatch ms @@ -1276,6 +1303,27 @@ cvtInjectivityAnnotation (TH.InjectivityAnn annLHS annRHS) ; annRHS' <- mapM tNameL annRHS ; returnL (Hs.InjectivityAnn annLHS' annRHS') } +cvtPatSynSigTy :: TH.Type -> CvtM (LHsType RdrName) +-- pattern synonym types are of peculiar shapes, which is why we treat +-- them separately from regular types; see NOTE [Pattern synonym +-- signatures and Template Haskell] +cvtPatSynSigTy (ForallT univs reqs (ForallT exis provs ty)) + | null exis, null provs = cvtType (ForallT univs reqs ty) + | null univs, null reqs = do { l <- getL + ; ty' <- cvtType (ForallT exis provs ty) + ; return $ L l (HsQualTy { hst_ctxt = L l [] + , hst_body = ty' }) } + | null reqs = do { l <- getL + ; univs' <- hsQTvExplicit <$> cvtTvs univs + ; ty' <- cvtType (ForallT exis provs ty) + ; let forTy = HsForAllTy { hst_bndrs = univs' + , hst_body = L l cxtTy } + cxtTy = HsQualTy { hst_ctxt = L l [] + , hst_body = ty' } + ; return $ L l forTy } + | otherwise = cvtType (ForallT univs reqs (ForallT exis provs ty)) +cvtPatSynSigTy ty = cvtType ty + ----------------------------------------------------------- cvtFixity :: TH.Fixity -> Hs.Fixity cvtFixity (TH.Fixity prec dir) = Hs.Fixity (show prec) prec (cvt_dir dir) @@ -1474,3 +1522,59 @@ the way System Names are printed. There's a small complication of course; see Note [Looking up Exact RdrNames] in RnEnv. -} + +{- +Note [Pattern synonym type signatures and Template Haskell] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In general, the type signature of a pattern synonym + + pattern P x1 x2 .. xn = <some-pattern> + +is of the form + + forall univs. reqs => forall exis. provs => t1 -> t2 -> ... -> tn -> t + +with the following parts: + + 1) the (possibly empty lists of) universally quantified type + variables `univs` and required constraints `reqs` on them. + 2) the (possibly empty lists of) existentially quantified type + variables `exis` and the provided constraints `provs` on them. + 3) the types `t1`, `t2`, .., `tn` of the pattern synonym's arguments x1, + x2, .., xn, respectively + 4) the type `t` of <some-pattern>, mentioning only universals from `univs`. + +Due to the two forall quantifiers and constraint contexts (either of +which might be empty), pattern synonym type signatures are treated +specially in `deSugar/DsMeta.hs`, `hsSyn/Convert.hs`, and +`typecheck/TcSplice.hs`: + + (a) When desugaring a pattern synonym from HsSyn to TH.Dec in + `deSugar/DsMeta.hs`, we represent its *full* type signature in TH, i.e.: + + ForallT univs reqs (ForallT exis provs ty) + (where ty is the AST representation of t1 -> t2 -> ... -> tn -> t) + + (b) When converting pattern synonyms from TH.Dec to HsSyn in + `hsSyn/Convert.hs`, we convert their TH type signatures back to an + appropriate Haskell pattern synonym type of the form + + forall univs. reqs => forall exis. provs => t1 -> t2 -> ... -> tn -> t + + where initial empty `univs` type variables or an empty `reqs` + constraint context are represented *explicitly* as `() =>`. + + (c) When reifying a pattern synonym in `typecheck/TcSplice.hs`, we always + return its *full* type, i.e.: + + ForallT univs reqs (ForallT exis provs ty) + (where ty is the AST representation of t1 -> t2 -> ... -> tn -> t) + +The key point is to always represent a pattern synonym's *full* type +in cases (a) and (c) to make it clear which of the two forall +quantifiers and/or constraint contexts are specified, and which are +not. See GHC's users guide on pattern synonyms for more information +about pattern synonym type signatures. + +-} diff --git a/compiler/hsSyn/HsTypes.hs b/compiler/hsSyn/HsTypes.hs index 04b0ae8c2d..bc78a7d270 100644 --- a/compiler/hsSyn/HsTypes.hs +++ b/compiler/hsSyn/HsTypes.hs @@ -984,22 +984,17 @@ splitHsAppTys f as = (f,as) -------------------------------- splitLHsPatSynTy :: LHsType name - -> ( [LHsTyVarBndr name] - , LHsContext name -- Required - , LHsContext name -- Provided - , LHsType name) -- Body -splitLHsPatSynTy ty - | L _ (HsQualTy { hst_ctxt = req, hst_body = ty2 }) <- ty1 - , L _ (HsQualTy { hst_ctxt = prov, hst_body = ty3 }) <- ty2 - = (tvs, req, prov, ty3) - - | L _ (HsQualTy { hst_ctxt = req, hst_body = ty2 }) <- ty1 - = (tvs, req, noLoc [], ty2) - - | otherwise - = (tvs, noLoc [], noLoc [], ty1) + -> ( [LHsTyVarBndr name] -- universals + , LHsContext name -- required constraints + , [LHsTyVarBndr name] -- existentials + , LHsContext name -- provided constraints + , LHsType name) -- body type +splitLHsPatSynTy ty = (univs, reqs, exis, provs, ty4) where - (tvs, ty1) = splitLHsForAllTy ty + (univs, ty1) = splitLHsForAllTy ty + (reqs, ty2) = splitLHsQualTy ty1 + (exis, ty3) = splitLHsForAllTy ty2 + (provs, ty4) = splitLHsQualTy ty3 splitLHsSigmaTy :: LHsType name -> ([LHsTyVarBndr name], LHsContext name, LHsType name) splitLHsSigmaTy ty diff --git a/compiler/hsSyn/HsUtils.hs b/compiler/hsSyn/HsUtils.hs index 35f146b55e..ee34773e1d 100644 --- a/compiler/hsSyn/HsUtils.hs +++ b/compiler/hsSyn/HsUtils.hs @@ -78,7 +78,7 @@ module HsUtils( collectLStmtsBinders, collectStmtsBinders, collectLStmtBinders, collectStmtBinders, - hsLTyClDeclBinders, hsTyClForeignBinders, hsPatSynBinders, + hsLTyClDeclBinders, hsTyClForeignBinders, hsPatSynSelectors, hsForeignDeclsBinders, hsGroupBinders, hsDataFamInstBinders, hsDataDefnBinders, @@ -784,8 +784,9 @@ collect_bind _ (AbsBinds { abs_exports = dbinds }) acc = map abe_poly dbinds ++ -- The only time we collect binders from a typechecked -- binding (hence see AbsBinds) is in zonking in TcHsSyn collect_bind _ (AbsBindsSig { abs_sig_export = poly }) acc = poly : acc -collect_bind omitPatSyn (PatSynBind (PSB { psb_id = L _ ps })) acc = - if omitPatSyn then acc else ps : acc +collect_bind omitPatSyn (PatSynBind (PSB { psb_id = L _ ps })) acc + | omitPatSyn = acc + | otherwise = ps : acc collectMethodBinders :: LHsBindsLR RdrName idR -> [Located RdrName] -- Used exclusively for the bindings of an instance decl which are all FunBinds @@ -935,26 +936,19 @@ hsForeignDeclsBinders foreign_decls | L decl_loc (ForeignImport { fd_name = L _ n }) <- foreign_decls] - ------------------- -hsPatSynBinders :: HsValBinds RdrName - -> ([Located RdrName], [Located RdrName]) --- Collect pattern-synonym binders only, not Ids --- See Note [SrcSpan for binders] -hsPatSynBinders (ValBindsIn binds _) = foldrBag addPatSynBndr ([],[]) binds -hsPatSynBinders _ = panic "hsPatSynBinders" - -addPatSynBndr :: LHsBindLR id id -> ([Located id], [Located id]) - -> ([Located id], [Located id]) -- (selectors, other) --- See Note [SrcSpan for binders] -addPatSynBndr bind (sels, pss) - | L bind_loc (PatSynBind (PSB { psb_id = L _ n - , psb_args = RecordPatSyn as })) <- bind - = (map recordPatSynSelectorId as ++ sels, L bind_loc n : pss) - | L bind_loc (PatSynBind (PSB { psb_id = L _ n})) <- bind - = (sels, L bind_loc n : pss) - | otherwise - = (sels, pss) +hsPatSynSelectors :: HsValBinds id -> [id] +-- Collects record pattern-synonym selectors only; the pattern synonym +-- names are collected by collectHsValBinders. +hsPatSynSelectors (ValBindsIn _ _) = panic "hsPatSynSelectors" +hsPatSynSelectors (ValBindsOut binds _) + = foldrBag addPatSynSelector [] . unionManyBags $ map snd binds + +addPatSynSelector:: LHsBind id -> [id] -> [id] +addPatSynSelector bind sels + | L _ (PatSynBind (PSB { psb_args = RecordPatSyn as })) <- bind + = map (unLoc . recordPatSynSelectorId) as ++ sels + | otherwise = sels ------------------- hsLInstDeclBinders :: LInstDecl name -> ([Located name], [LFieldOcc name]) diff --git a/compiler/prelude/THNames.hs b/compiler/prelude/THNames.hs index 671fe490c8..e3a58cccdd 100644 --- a/compiler/prelude/THNames.hs +++ b/compiler/prelude/THNames.hs @@ -71,7 +71,7 @@ templateHaskellNames = [ dataFamilyDName, openTypeFamilyDName, closedTypeFamilyDName, dataInstDName, newtypeInstDName, tySynInstDName, infixLDName, infixRDName, infixNDName, - roleAnnotDName, + roleAnnotDName, patSynDName, patSynSigDName, -- Cxt cxtName, @@ -87,6 +87,10 @@ templateHaskellNames = [ bangTypeName, -- VarBangType varBangTypeName, + -- PatSynDir (for pattern synonyms) + unidirPatSynName, implBidirPatSynName, explBidirPatSynName, + -- PatSynArgs (for pattern synonyms) + prefixPatSynName, infixPatSynName, recordPatSynName, -- Type forallTName, varTName, conTName, appTName, equalityTName, tupleTName, unboxedTupleTName, arrowTName, listTName, sigTName, litTName, @@ -325,10 +329,10 @@ funDName, valDName, dataDName, newtypeDName, tySynDName, classDName, instanceWithOverlapDName, sigDName, forImpDName, pragInlDName, pragSpecDName, pragSpecInlDName, pragSpecInstDName, pragRuleDName, pragAnnDName, - standaloneDerivDName, defaultSigDName, - dataInstDName, newtypeInstDName, tySynInstDName, - dataFamilyDName, openTypeFamilyDName, closedTypeFamilyDName, - infixLDName, infixRDName, infixNDName, roleAnnotDName :: Name + standaloneDerivDName, defaultSigDName, dataInstDName, newtypeInstDName, + tySynInstDName, dataFamilyDName, openTypeFamilyDName, closedTypeFamilyDName, + infixLDName, infixRDName, infixNDName, roleAnnotDName, patSynDName, + patSynSigDName :: Name funDName = libFun (fsLit "funD") funDIdKey valDName = libFun (fsLit "valD") valDIdKey dataDName = libFun (fsLit "dataD") dataDIdKey @@ -336,8 +340,7 @@ newtypeDName = libFun (fsLit "newtypeD") newtypeDIdKey tySynDName = libFun (fsLit "tySynD") tySynDIdKey classDName = libFun (fsLit "classD") classDIdKey instanceWithOverlapDName - = libFun (fsLit "instanceWithOverlapD") - instanceWithOverlapDIdKey + = libFun (fsLit "instanceWithOverlapD") instanceWithOverlapDIdKey standaloneDerivDName = libFun (fsLit "standaloneDerivD") standaloneDerivDIdKey sigDName = libFun (fsLit "sigD") sigDIdKey defaultSigDName = libFun (fsLit "defaultSigD") defaultSigDIdKey @@ -358,6 +361,8 @@ infixLDName = libFun (fsLit "infixLD") infixLDIdKey infixRDName = libFun (fsLit "infixRD") infixRDIdKey infixNDName = libFun (fsLit "infixND") infixNDIdKey roleAnnotDName = libFun (fsLit "roleAnnotD") roleAnnotDIdKey +patSynDName = libFun (fsLit "patSynD") patSynDIdKey +patSynSigDName = libFun (fsLit "patSynSigD") patSynSigDIdKey -- type Ctxt = ... cxtName :: Name @@ -396,6 +401,18 @@ bangTypeName = libFun (fsLit "bangType") bangTKey varBangTypeName :: Name varBangTypeName = libFun (fsLit "varBangType") varBangTKey +-- data PatSynDir = ... +unidirPatSynName, implBidirPatSynName, explBidirPatSynName :: Name +unidirPatSynName = libFun (fsLit "unidir") unidirPatSynIdKey +implBidirPatSynName = libFun (fsLit "implBidir") implBidirPatSynIdKey +explBidirPatSynName = libFun (fsLit "explBidir") explBidirPatSynIdKey + +-- data PatSynArgs = ... +prefixPatSynName, infixPatSynName, recordPatSynName :: Name +prefixPatSynName = libFun (fsLit "prefixPatSyn") prefixPatSynIdKey +infixPatSynName = libFun (fsLit "infixPatSyn") infixPatSynIdKey +recordPatSynName = libFun (fsLit "recordPatSyn") recordPatSynIdKey + -- data Type = ... forallTName, varTName, conTName, tupleTName, unboxedTupleTName, arrowTName, listTName, appTName, sigTName, equalityTName, litTName, @@ -557,7 +574,6 @@ overlappingDataConName = thCon (fsLit "Overlapping") overlappingDataConKey overlapsDataConName = thCon (fsLit "Overlaps") overlapsDataConKey incoherentDataConName = thCon (fsLit "Incoherent") incoherentDataConKey - {- ********************************************************************* * * Class keys @@ -663,8 +679,6 @@ overlappingDataConKey = mkPreludeDataConUnique 110 overlapsDataConKey = mkPreludeDataConUnique 111 incoherentDataConKey = mkPreludeDataConUnique 112 - - {- ********************************************************************* * * Id keys @@ -713,8 +727,9 @@ liftStringIdKey :: Unique liftStringIdKey = mkPreludeMiscIdUnique 230 -- data Pat = ... -litPIdKey, varPIdKey, tupPIdKey, unboxedTupPIdKey, conPIdKey, infixPIdKey, tildePIdKey, bangPIdKey, - asPIdKey, wildPIdKey, recPIdKey, listPIdKey, sigPIdKey, viewPIdKey :: Unique +litPIdKey, varPIdKey, tupPIdKey, unboxedTupPIdKey, conPIdKey, infixPIdKey, + tildePIdKey, bangPIdKey, asPIdKey, wildPIdKey, recPIdKey, listPIdKey, + sigPIdKey, viewPIdKey :: Unique litPIdKey = mkPreludeMiscIdUnique 240 varPIdKey = mkPreludeMiscIdUnique 241 tupPIdKey = mkPreludeMiscIdUnique 242 @@ -782,99 +797,114 @@ unboundVarEIdKey = mkPreludeMiscIdUnique 297 -- type FieldExp = ... fieldExpIdKey :: Unique -fieldExpIdKey = mkPreludeMiscIdUnique 310 +fieldExpIdKey = mkPreludeMiscIdUnique 305 -- data Body = ... guardedBIdKey, normalBIdKey :: Unique -guardedBIdKey = mkPreludeMiscIdUnique 311 -normalBIdKey = mkPreludeMiscIdUnique 312 +guardedBIdKey = mkPreludeMiscIdUnique 306 +normalBIdKey = mkPreludeMiscIdUnique 307 -- data Guard = ... normalGEIdKey, patGEIdKey :: Unique -normalGEIdKey = mkPreludeMiscIdUnique 313 -patGEIdKey = mkPreludeMiscIdUnique 314 +normalGEIdKey = mkPreludeMiscIdUnique 308 +patGEIdKey = mkPreludeMiscIdUnique 309 -- data Stmt = ... bindSIdKey, letSIdKey, noBindSIdKey, parSIdKey :: Unique -bindSIdKey = mkPreludeMiscIdUnique 320 -letSIdKey = mkPreludeMiscIdUnique 321 -noBindSIdKey = mkPreludeMiscIdUnique 322 -parSIdKey = mkPreludeMiscIdUnique 323 +bindSIdKey = mkPreludeMiscIdUnique 310 +letSIdKey = mkPreludeMiscIdUnique 311 +noBindSIdKey = mkPreludeMiscIdUnique 312 +parSIdKey = mkPreludeMiscIdUnique 313 -- data Dec = ... -funDIdKey, valDIdKey, dataDIdKey, newtypeDIdKey, tySynDIdKey, - classDIdKey, instanceWithOverlapDIdKey, sigDIdKey, forImpDIdKey, - pragInlDIdKey, - pragSpecDIdKey, pragSpecInlDIdKey, pragSpecInstDIdKey, pragRuleDIdKey, - pragAnnDIdKey, defaultSigDIdKey, dataFamilyDIdKey, openTypeFamilyDIdKey, - closedTypeFamilyDIdKey, dataInstDIdKey, newtypeInstDIdKey, tySynInstDIdKey, - standaloneDerivDIdKey, infixLDIdKey, infixRDIdKey, infixNDIdKey, - roleAnnotDIdKey :: Unique -funDIdKey = mkPreludeMiscIdUnique 330 -valDIdKey = mkPreludeMiscIdUnique 331 -dataDIdKey = mkPreludeMiscIdUnique 332 -newtypeDIdKey = mkPreludeMiscIdUnique 333 -tySynDIdKey = mkPreludeMiscIdUnique 334 -classDIdKey = mkPreludeMiscIdUnique 335 -instanceWithOverlapDIdKey = mkPreludeMiscIdUnique 336 -sigDIdKey = mkPreludeMiscIdUnique 337 -forImpDIdKey = mkPreludeMiscIdUnique 338 -pragInlDIdKey = mkPreludeMiscIdUnique 339 -pragSpecDIdKey = mkPreludeMiscIdUnique 340 -pragSpecInlDIdKey = mkPreludeMiscIdUnique 341 -pragSpecInstDIdKey = mkPreludeMiscIdUnique 342 -pragRuleDIdKey = mkPreludeMiscIdUnique 343 -pragAnnDIdKey = mkPreludeMiscIdUnique 344 -dataFamilyDIdKey = mkPreludeMiscIdUnique 345 -openTypeFamilyDIdKey = mkPreludeMiscIdUnique 346 -dataInstDIdKey = mkPreludeMiscIdUnique 347 -newtypeInstDIdKey = mkPreludeMiscIdUnique 348 -tySynInstDIdKey = mkPreludeMiscIdUnique 349 -closedTypeFamilyDIdKey = mkPreludeMiscIdUnique 350 -infixLDIdKey = mkPreludeMiscIdUnique 352 -infixRDIdKey = mkPreludeMiscIdUnique 353 -infixNDIdKey = mkPreludeMiscIdUnique 354 -roleAnnotDIdKey = mkPreludeMiscIdUnique 355 -standaloneDerivDIdKey = mkPreludeMiscIdUnique 356 -defaultSigDIdKey = mkPreludeMiscIdUnique 357 +funDIdKey, valDIdKey, dataDIdKey, newtypeDIdKey, tySynDIdKey, classDIdKey, + instanceWithOverlapDIdKey, instanceDIdKey, sigDIdKey, forImpDIdKey, + pragInlDIdKey, pragSpecDIdKey, pragSpecInlDIdKey, pragSpecInstDIdKey, + pragRuleDIdKey, pragAnnDIdKey, defaultSigDIdKey, dataFamilyDIdKey, + openTypeFamilyDIdKey, closedTypeFamilyDIdKey, dataInstDIdKey, + newtypeInstDIdKey, tySynInstDIdKey, standaloneDerivDIdKey, infixLDIdKey, + infixRDIdKey, infixNDIdKey, roleAnnotDIdKey, patSynDIdKey, + patSynSigDIdKey :: Unique +funDIdKey = mkPreludeMiscIdUnique 320 +valDIdKey = mkPreludeMiscIdUnique 321 +dataDIdKey = mkPreludeMiscIdUnique 322 +newtypeDIdKey = mkPreludeMiscIdUnique 323 +tySynDIdKey = mkPreludeMiscIdUnique 324 +classDIdKey = mkPreludeMiscIdUnique 325 +instanceWithOverlapDIdKey = mkPreludeMiscIdUnique 326 +instanceDIdKey = mkPreludeMiscIdUnique 327 +sigDIdKey = mkPreludeMiscIdUnique 328 +forImpDIdKey = mkPreludeMiscIdUnique 329 +pragInlDIdKey = mkPreludeMiscIdUnique 330 +pragSpecDIdKey = mkPreludeMiscIdUnique 331 +pragSpecInlDIdKey = mkPreludeMiscIdUnique 332 +pragSpecInstDIdKey = mkPreludeMiscIdUnique 333 +pragRuleDIdKey = mkPreludeMiscIdUnique 334 +pragAnnDIdKey = mkPreludeMiscIdUnique 335 +dataFamilyDIdKey = mkPreludeMiscIdUnique 336 +openTypeFamilyDIdKey = mkPreludeMiscIdUnique 337 +dataInstDIdKey = mkPreludeMiscIdUnique 338 +newtypeInstDIdKey = mkPreludeMiscIdUnique 339 +tySynInstDIdKey = mkPreludeMiscIdUnique 340 +closedTypeFamilyDIdKey = mkPreludeMiscIdUnique 341 +infixLDIdKey = mkPreludeMiscIdUnique 342 +infixRDIdKey = mkPreludeMiscIdUnique 343 +infixNDIdKey = mkPreludeMiscIdUnique 344 +roleAnnotDIdKey = mkPreludeMiscIdUnique 345 +standaloneDerivDIdKey = mkPreludeMiscIdUnique 346 +defaultSigDIdKey = mkPreludeMiscIdUnique 347 +patSynDIdKey = mkPreludeMiscIdUnique 348 +patSynSigDIdKey = mkPreludeMiscIdUnique 349 -- type Cxt = ... cxtIdKey :: Unique -cxtIdKey = mkPreludeMiscIdUnique 360 +cxtIdKey = mkPreludeMiscIdUnique 350 -- data SourceUnpackedness = ... noSourceUnpackednessKey, sourceNoUnpackKey, sourceUnpackKey :: Unique -noSourceUnpackednessKey = mkPreludeMiscIdUnique 361 -sourceNoUnpackKey = mkPreludeMiscIdUnique 362 -sourceUnpackKey = mkPreludeMiscIdUnique 363 +noSourceUnpackednessKey = mkPreludeMiscIdUnique 351 +sourceNoUnpackKey = mkPreludeMiscIdUnique 352 +sourceUnpackKey = mkPreludeMiscIdUnique 353 -- data SourceStrictness = ... noSourceStrictnessKey, sourceLazyKey, sourceStrictKey :: Unique -noSourceStrictnessKey = mkPreludeMiscIdUnique 364 -sourceLazyKey = mkPreludeMiscIdUnique 365 -sourceStrictKey = mkPreludeMiscIdUnique 366 +noSourceStrictnessKey = mkPreludeMiscIdUnique 354 +sourceLazyKey = mkPreludeMiscIdUnique 355 +sourceStrictKey = mkPreludeMiscIdUnique 356 -- data Con = ... normalCIdKey, recCIdKey, infixCIdKey, forallCIdKey, gadtCIdKey, recGadtCIdKey :: Unique -normalCIdKey = mkPreludeMiscIdUnique 370 -recCIdKey = mkPreludeMiscIdUnique 371 -infixCIdKey = mkPreludeMiscIdUnique 372 -forallCIdKey = mkPreludeMiscIdUnique 373 -gadtCIdKey = mkPreludeMiscIdUnique 374 -recGadtCIdKey = mkPreludeMiscIdUnique 375 +normalCIdKey = mkPreludeMiscIdUnique 357 +recCIdKey = mkPreludeMiscIdUnique 358 +infixCIdKey = mkPreludeMiscIdUnique 359 +forallCIdKey = mkPreludeMiscIdUnique 360 +gadtCIdKey = mkPreludeMiscIdUnique 361 +recGadtCIdKey = mkPreludeMiscIdUnique 362 -- data Bang = ... bangIdKey :: Unique -bangIdKey = mkPreludeMiscIdUnique 376 +bangIdKey = mkPreludeMiscIdUnique 363 -- type BangType = ... bangTKey :: Unique -bangTKey = mkPreludeMiscIdUnique 377 +bangTKey = mkPreludeMiscIdUnique 364 -- type VarBangType = ... varBangTKey :: Unique -varBangTKey = mkPreludeMiscIdUnique 378 +varBangTKey = mkPreludeMiscIdUnique 365 + +-- data PatSynDir = ... +unidirPatSynIdKey, implBidirPatSynIdKey, explBidirPatSynIdKey :: Unique +unidirPatSynIdKey = mkPreludeMiscIdUnique 366 +implBidirPatSynIdKey = mkPreludeMiscIdUnique 367 +explBidirPatSynIdKey = mkPreludeMiscIdUnique 368 + +-- data PatSynArgs = ... +prefixPatSynIdKey, infixPatSynIdKey, recordPatSynIdKey :: Unique +prefixPatSynIdKey = mkPreludeMiscIdUnique 369 +infixPatSynIdKey = mkPreludeMiscIdUnique 370 +recordPatSynIdKey = mkPreludeMiscIdUnique 371 -- data Type = ... forallTIdKey, varTIdKey, conTIdKey, tupleTIdKey, unboxedTupleTIdKey, arrowTIdKey, diff --git a/compiler/typecheck/TcSplice.hs b/compiler/typecheck/TcSplice.hs index 5483d0d432..828cb95ad7 100644 --- a/compiler/typecheck/TcSplice.hs +++ b/compiler/typecheck/TcSplice.hs @@ -89,7 +89,7 @@ import LoadIface import Class import TyCon import CoAxiom -import PatSyn ( patSynName ) +import PatSyn import ConLike import DataCon import TcEvidence( TcEvBinds(..) ) @@ -1272,8 +1272,11 @@ reifyThing (AGlobal (AConLike (RealDataCon dc))) ; return (TH.DataConI (reifyName name) ty (reifyName (dataConOrigTyCon dc))) } + reifyThing (AGlobal (AConLike (PatSynCon ps))) - = noTH (sLit "pattern synonyms") (ppr $ patSynName ps) + = do { let name = reifyName ps + ; ty <- reifyPatSynType (patSynSig ps) + ; return (TH.PatSynI name ty) } reifyThing (ATcId {tct_id = id}) = do { ty1 <- zonkTcType (idType id) -- Make use of all the info we have, even @@ -1636,6 +1639,20 @@ reifyTyLit (StrTyLit s) = return (TH.StrTyLit (unpackFS s)) reifyTypes :: [Type] -> TcM [TH.Type] reifyTypes = mapM reifyType +reifyPatSynType + :: ([TyVar], ThetaType, [TyVar], ThetaType, [Type], Type) -> TcM TH.Type +-- reifies a pattern synonym's type and returns its *complete* type +-- signature; see NOTE [Pattern synonym signatures and Template +-- Haskell] +reifyPatSynType (univTyVars, req, exTyVars, prov, argTys, resTy) + = do { univTyVars' <- reifyTyVars univTyVars Nothing + ; req' <- reifyCxt req + ; exTyVars' <- reifyTyVars exTyVars Nothing + ; prov' <- reifyCxt prov + ; tau' <- reifyType (mkFunTys argTys resTy) + ; return $ TH.ForallT univTyVars' req' + $ TH.ForallT exTyVars' prov' tau' } + reifyKind :: Kind -> TcM TH.Kind reifyKind ki = do { let (kis, ki') = splitFunTys ki diff --git a/libraries/ghci/GHCi/TH/Binary.hs b/libraries/ghci/GHCi/TH/Binary.hs index ab9b35525a..0bdc756870 100644 --- a/libraries/ghci/GHCi/TH/Binary.hs +++ b/libraries/ghci/GHCi/TH/Binary.hs @@ -59,6 +59,8 @@ instance Binary TH.Clause instance Binary TH.InjectivityAnn instance Binary TH.FamilyResultSig instance Binary TH.TypeFamilyHead +instance Binary TH.PatSynDir +instance Binary TH.PatSynArgs -- We need Binary TypeRep for serializing annotations diff --git a/libraries/template-haskell/Language/Haskell/TH.hs b/libraries/template-haskell/Language/Haskell/TH.hs index 3bca8eaeef..5bd610cd76 100644 --- a/libraries/template-haskell/Language/Haskell/TH.hs +++ b/libraries/template-haskell/Language/Haskell/TH.hs @@ -73,20 +73,22 @@ module Language.Haskell.TH( Inline(..), RuleMatch(..), Phases(..), RuleBndr(..), AnnTarget(..), FunDep(..), FamFlavour(..), TySynEqn(..), TypeFamilyHead(..), Fixity(..), FixityDirection(..), defaultFixity, maxPrecedence, + PatSynDir(..), PatSynArgs(..), -- ** Expressions Exp(..), Match(..), Body(..), Guard(..), Stmt(..), Range(..), Lit(..), -- ** Patterns Pat(..), FieldExp, FieldPat, -- ** Types Type(..), TyVarBndr(..), TyLit(..), Kind, Cxt, Pred, Syntax.Role(..), - FamilyResultSig(..), Syntax.InjectivityAnn(..), + FamilyResultSig(..), Syntax.InjectivityAnn(..), PatSynType, -- * Library functions -- ** Abbreviations InfoQ, ExpQ, DecQ, DecsQ, ConQ, TypeQ, TyLitQ, CxtQ, PredQ, MatchQ, ClauseQ, BodyQ, GuardQ, StmtQ, RangeQ, SourceStrictnessQ, SourceUnpackednessQ, BangTypeQ, VarBangTypeQ, StrictTypeQ, - VarStrictTypeQ, PatQ, FieldPatQ, RuleBndrQ, TySynEqnQ, + VarStrictTypeQ, PatQ, FieldPatQ, RuleBndrQ, TySynEqnQ, PatSynDirQ, + PatSynArgsQ, -- ** Constructors lifted to 'Q' -- *** Literals @@ -160,7 +162,11 @@ module Language.Haskell.TH( pragInlD, pragSpecD, pragSpecInlD, pragSpecInstD, pragRuleD, pragAnnD, pragLineD, - -- * Pretty-printer + -- **** Pattern Synonyms + patSynD, patSynSigD, unidir, implBidir, explBidir, prefixPatSyn, + infixPatSyn, recordPatSyn, + + -- * Pretty-printer Ppr(..), pprint, pprExp, pprLit, pprPat, pprParendType ) where diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs index 6971970524..d4529e1915 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Lib.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs @@ -46,6 +46,8 @@ type VarStrictTypeQ = Q VarStrictType type FieldExpQ = Q FieldExp type RuleBndrQ = Q RuleBndr type TySynEqnQ = Q TySynEqn +type PatSynDirQ = Q PatSynDir +type PatSynArgsQ = Q PatSynArgs -- must be defined here for DsMeta to find it type Role = TH.Role @@ -531,6 +533,20 @@ defaultSigD n tyq = ty <- tyq return $ DefaultSigD n ty +-- | Pattern synonym declaration +patSynD :: Name -> PatSynArgsQ -> PatSynDirQ -> PatQ -> DecQ +patSynD name args dir pat = do + args' <- args + dir' <- dir + pat' <- pat + return (PatSynD name args' dir' pat') + +-- | Pattern synonym type signature +patSynSigD :: Name -> TypeQ -> DecQ +patSynSigD nm ty = + do ty' <- ty + return $ PatSynSigD nm ty' + tySynEqn :: [TypeQ] -> TypeQ -> TySynEqnQ tySynEqn lhs rhs = do @@ -706,8 +722,6 @@ numTyLit n = if n >= 0 then return (NumTyLit n) strTyLit :: String -> TyLitQ strTyLit s = return (StrTyLit s) - - ------------------------------------------------------------------------------- -- * Kind @@ -818,6 +832,27 @@ typeAnnotation = TypeAnnotation moduleAnnotation :: AnnTarget moduleAnnotation = ModuleAnnotation +------------------------------------------------------------------------------- +-- * Pattern Synonyms (sub constructs) + +unidir, implBidir :: PatSynDirQ +unidir = return Unidir +implBidir = return ImplBidir + +explBidir :: [ClauseQ] -> PatSynDirQ +explBidir cls = do + cls' <- sequence cls + return (ExplBidir cls') + +prefixPatSyn :: [Name] -> PatSynArgsQ +prefixPatSyn args = return $ PrefixPatSyn args + +recordPatSyn :: [Name] -> PatSynArgsQ +recordPatSyn sels = return $ RecordPatSyn sels + +infixPatSyn :: Name -> Name -> PatSynArgsQ +infixPatSyn arg1 arg2 = return $ InfixPatSyn arg1 arg2 + -------------------------------------------------------------- -- * Useful helper function diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs index 2a56620684..ca74db7e45 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs @@ -19,10 +19,10 @@ nestDepth = 4 type Precedence = Int appPrec, unopPrec, opPrec, noPrec :: Precedence -appPrec = 3 -- Argument of a function application -opPrec = 2 -- Argument of an infix operator -unopPrec = 1 -- Argument of an unresolved infix operator -noPrec = 0 -- Others +appPrec = 3 -- Argument of a function application +opPrec = 2 -- Argument of an infix operator +unopPrec = 1 -- Argument of an unresolved infix operator +noPrec = 0 -- Others parensIf :: Bool -> Doc -> Doc parensIf True d = parens d @@ -59,6 +59,7 @@ instance Ppr Info where = text "Class op from" <+> ppr cls <> colon <+> ppr_sig v ty ppr (DataConI v ty tc) = text "Constructor from" <+> ppr tc <> colon <+> ppr_sig v ty + ppr (PatSynI nm ty) = pprPatSynSig nm ty ppr (TyVarI v ty) = text "Type variable" <+> ppr v <+> equals <+> ppr ty ppr (VarI v ty mb_d) @@ -75,6 +76,24 @@ pprFixity v (Fixity i d) = ppr_fix d <+> int i <+> ppr v ppr_fix InfixL = text "infixl" ppr_fix InfixN = text "infix" +-- | Pretty prints a pattern synonym type signature +pprPatSynSig :: Name -> PatSynType -> Doc +pprPatSynSig nm ty + = text "pattern" <+> pprPrefixOcc nm <+> dcolon <+> pprPatSynType ty + +-- | Pretty prints a pattern synonym's type; follows the usual +-- conventions to print a pattern synonym type compactly, yet +-- unambiguously. See the note on 'PatSynType' and the section on +-- pattern synonyms in the GHC users guide for more information. +pprPatSynType :: PatSynType -> Doc +pprPatSynType ty@(ForallT uniTys reqs ty'@(ForallT exTys provs ty'')) + | null exTys, null provs = ppr (ForallT uniTys reqs ty'') + | null uniTys, null reqs = noreqs <+> ppr ty' + | null reqs = forall uniTys <+> noreqs <+> ppr ty' + | otherwise = ppr ty + where noreqs = text "() =>" + forall tvs = text "forall" <+> (hsep (map ppr tvs)) <+> text "." +pprPatSynType ty = ppr ty ------------------------------ instance Ppr Module where @@ -330,15 +349,22 @@ ppr_dec _ (ClosedTypeFamilyD tfhead@(TypeFamilyHead tc _ _ _) eqns) where ppr_eqn (TySynEqn lhs rhs) = ppr tc <+> sep (map pprParendType lhs) <+> text "=" <+> ppr rhs - ppr_dec _ (RoleAnnotD name roles) = hsep [ text "type role", ppr name ] <+> hsep (map ppr roles) - ppr_dec _ (StandaloneDerivD cxt ty) = hsep [ text "deriving instance", pprCxt cxt, ppr ty ] - ppr_dec _ (DefaultSigD n ty) = hsep [ text "default", pprPrefixOcc n, dcolon, ppr ty ] +ppr_dec _ (PatSynD name args dir pat) + = text "pattern" <+> pprNameArgs <+> ppr dir <+> pprPatRHS + where + pprNameArgs | InfixPatSyn a1 a2 <- args = ppr a1 <+> ppr name <+> ppr a2 + | otherwise = ppr name <+> ppr args + pprPatRHS | ExplBidir cls <- dir = hang (ppr pat <+> text "where") + nestDepth (ppr name <+> ppr cls) + | otherwise = ppr pat +ppr_dec _ (PatSynSigD name ty) + = pprPatSynSig name ty ppr_overlap :: Overlap -> Doc @@ -533,13 +559,28 @@ instance Ppr Con where ppr (RecGadtC c vsts ty) = commaSepApplied c <+> dcolon <+> pprRecFields vsts ty +instance Ppr PatSynDir where + ppr Unidir = text "<-" + ppr ImplBidir = text "=" + ppr (ExplBidir _) = text "<-" + -- the ExplBidir's clauses are pretty printed together with the + -- entire pattern synonym; so only print the direction here. + +instance Ppr PatSynArgs where + ppr (PrefixPatSyn args) = sep $ map ppr args + ppr (InfixPatSyn a1 a2) = ppr a1 <+> ppr a2 + ppr (RecordPatSyn sels) = braces $ sep (punctuate comma (map ppr sels)) + commaSepApplied :: [Name] -> Doc commaSepApplied = commaSepWith (pprName' Applied) pprForall :: [TyVarBndr] -> Cxt -> Doc -pprForall ns ctxt - = text "forall" <+> hsep (map ppr ns) - <+> char '.' <+> pprCxt ctxt +pprForall tvs cxt + -- even in the case without any tvs, there could be a non-empty + -- context cxt (e.g., in the case of pattern synonyms, where there + -- are multiple forall binders and contexts). + | [] <- tvs = pprCxt cxt + | otherwise = text "forall" <+> hsep (map ppr tvs) <+> char '.' <+> pprCxt cxt pprRecFields :: [(Name, Strict, Type)] -> Type -> Doc pprRecFields vsts ty @@ -639,9 +680,7 @@ pprUInfixT (UInfixT x n y) = pprUInfixT x <+> pprName' Infix n <+> pprUInfixT y pprUInfixT t = ppr t instance Ppr Type where - ppr (ForallT tvars ctxt ty) - = text "forall" <+> hsep (map ppr tvars) <+> text "." - <+> sep [pprCxt ctxt, ppr ty] + ppr (ForallT tvars ctxt ty) = sep [pprForall tvars ctxt, ppr ty] ppr ty = pprTyApp (split ty) -- Works, in a degnerate way, for SigT, and puts parens round (ty :: kind) -- See Note [Pretty-printing kind signatures] diff --git a/libraries/template-haskell/Language/Haskell/TH/PprLib.hs b/libraries/template-haskell/Language/Haskell/TH/PprLib.hs index 378888d77f..32980ab6cc 100644 --- a/libraries/template-haskell/Language/Haskell/TH/PprLib.hs +++ b/libraries/template-haskell/Language/Haskell/TH/PprLib.hs @@ -137,7 +137,7 @@ instance Show Name where show (Name occ (NameU u)) = occString occ ++ "_" ++ show (I# u) show (Name occ NameS) = occString occ show (Name occ (NameG ns m)) = modString m ++ "." ++ occString occ - + data Name = Name OccName NameFlavour data NameFlavour diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs index 8022f94b87..fc9c80d140 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs @@ -1231,6 +1231,11 @@ data Info Type ParentName + -- | A pattern synonym. + | PatSynI + Name + PatSynType + {- | A \"value\" variable (as opposed to a type variable, see 'TyVarI'). @@ -1545,9 +1550,21 @@ data Dec | ClosedTypeFamilyD TypeFamilyHead [TySynEqn] -- ^ @{ type family F a b = (r :: *) | r -> a where ... }@ - | RoleAnnotD Name [Role] -- ^ @{ type role T nominal representational }@ - | StandaloneDerivD Cxt Type -- ^ @{ deriving instance Ord a => Ord (Foo a) }@ - | DefaultSigD Name Type -- ^ @{ default size :: Data a => a -> Int }@ + | RoleAnnotD Name [Role] -- ^ @{ type role T nominal representational }@ + | StandaloneDerivD Cxt Type -- ^ @{ deriving instance Ord a => Ord (Foo a) }@ + | DefaultSigD Name Type -- ^ @{ default size :: Data a => a -> Int }@ + + -- | Pattern Synonyms + | PatSynD Name PatSynArgs PatSynDir Pat + -- ^ @{ pattern P v1 v2 .. vn <- p }@ unidirectional or + -- @{ pattern P v1 v2 .. vn = p }@ implicit bidirectional or + -- @{ pattern P v1 v2 .. vn <- p + -- where P v1 v2 .. vn = e }@ explicit bidirectional + -- + -- also, besides prefix pattern synonyms, both infix and record + -- pattern synonyms are supported. See 'PatSynArgs' for details + + | PatSynSigD Name PatSynType -- ^ A pattern synonym's type signature. deriving( Show, Eq, Ord, Data, Typeable, Generic ) -- | Varieties of allowed instance overlap. @@ -1559,11 +1576,58 @@ data Overlap = Overlappable -- ^ May be overlapped by more specific instances -- available. deriving( Show, Eq, Ord, Data, Typeable, Generic ) --- | Common elements of 'OpenTypeFamilyD' and 'ClosedTypeFamilyD'. --- By analogy with with "head" for type classes and type class instances as +-- | A Pattern synonym's type. Note that a pattern synonym's *fully* +-- specified type has a peculiar shape coming with two forall +-- quantifiers and two constraint contexts. For example, consider the +-- pattern synonym +-- +-- pattern P x1 x2 ... xn = <some-pattern> +-- +-- P's complete type is of the following form +-- +-- forall universals. required constraints +-- => forall existentials. provided constraints +-- => t1 -> t2 -> ... -> tn -> t +-- +-- consisting of four parts: +-- +-- 1) the (possibly empty lists of) universally quantified type +-- variables and required constraints on them. +-- 2) the (possibly empty lists of) existentially quantified +-- type variables and the provided constraints on them. +-- 3) the types t1, t2, .., tn of x1, x2, .., xn, respectively +-- 4) the type t of <some-pattern>, mentioning only universals. +-- +-- Pattern synonym types interact with TH when (a) reifying a pattern +-- synonym, (b) pretty printing, or (c) specifying a pattern synonym's +-- type signature explicitly: +-- +-- (a) Reification always returns a pattern synonym's *fully* specified +-- type in abstract syntax. +-- +-- (b) Pretty printing via 'pprPatSynType' abbreviates a pattern +-- synonym's type unambiguously in concrete syntax: The rule of +-- thumb is to print initial empty universals and the required +-- context as `() =>`, if existentials and a provided context +-- follow. If only universals and their required context, but no +-- existentials are specified, only the universals and their +-- required context are printed. If both or none are specified, so +-- both (or none) are printed. +-- +-- (c) When specifying a pattern synonym's type explicitly with +-- 'PatSynSigD' either one of the universals, the existentials, or +-- their contexts may be left empty. +-- +-- See the GHC users guide for more information on pattern synonyms +-- and their types: https://downloads.haskell.org/~ghc/latest/docs/html/ +-- users_guide/syntax-extns.html#pattern-synonyms. +type PatSynType = Type + +-- | Common elements of 'OpenTypeFamilyD' and 'ClosedTypeFamilyD'. By +-- analogy with "head" for type classes and type class instances as -- defined in /Type classes: an exploration of the design space/, the --- @TypeFamilyHead@ is defined to be the elements of the declaration between --- @type family@ and @where@. +-- @TypeFamilyHead@ is defined to be the elements of the declaration +-- between @type family@ and @where@. data TypeFamilyHead = TypeFamilyHead Name [TyVarBndr] FamilyResultSig (Maybe InjectivityAnn) deriving( Show, Eq, Ord, Data, Typeable, Generic ) @@ -1707,6 +1771,20 @@ type StrictType = BangType -- 'VarBangType'. type VarStrictType = VarBangType +-- | A pattern synonym's directionality. +data PatSynDir + = Unidir -- ^ @pattern P x {<-} p@ + | ImplBidir -- ^ @pattern P x {=} p@ + | ExplBidir [Clause] -- ^ @pattern P x {<-} p where P x = e@ + deriving( Show, Eq, Ord, Data, Typeable, Generic ) + +-- | A pattern synonym's argument type. +data PatSynArgs + = PrefixPatSyn [Name] -- ^ @pattern P {x y z} = p@ + | InfixPatSyn Name Name -- ^ @pattern {x P y} = p@ + | RecordPatSyn [Name] -- ^ @pattern P { {x,y,z} } = p@ + deriving( Show, Eq, Ord, Data, Typeable, Generic ) + data Type = ForallT [TyVarBndr] Cxt Type -- ^ @forall \<vars\>. \<ctxt\> -> \<type\>@ | AppT Type Type -- ^ @T a b@ | SigT Type Kind -- ^ @t :: k@ diff --git a/testsuite/tests/quotes/T8759a.stderr b/testsuite/tests/quotes/T8759a.stderr deleted file mode 100644 index ff0fd495df..0000000000 --- a/testsuite/tests/quotes/T8759a.stderr +++ /dev/null @@ -1,4 +0,0 @@ - -T8759a.hs:5:7: - pattern synonyms not (yet) handled by Template Haskell - pattern Q = False diff --git a/testsuite/tests/quotes/all.T b/testsuite/tests/quotes/all.T index c34a207292..87081a5dc6 100644 --- a/testsuite/tests/quotes/all.T +++ b/testsuite/tests/quotes/all.T @@ -13,7 +13,7 @@ test('T5721', normal, compile, ['-v0']) test('T6062', normal, compile, ['-v0']) test('T8455', normal, compile, ['-v0']) test('T8633', normal, compile_and_run, ['']) -test('T8759a', normal, compile_fail, ['-v0']) +test('T8759a', normal, compile, ['-v0']) test('T9824', normal, compile, ['-v0']) test('T10384', normal, compile_fail, ['']) diff --git a/testsuite/tests/th/T10019.stdout b/testsuite/tests/th/T10019.stdout index e079405309..fb87a9bd9a 100644 --- a/testsuite/tests/th/T10019.stdout +++ b/testsuite/tests/th/T10019.stdout @@ -1 +1 @@ -"Constructor from Ghci1.Option: Ghci1.Some :: forall (a_0 :: *) . a_0 ->\n Ghci1.Option a_0" +"Constructor from Ghci1.Option: Ghci1.Some :: forall (a_0 :: *) .\n a_0 -> Ghci1.Option a_0" diff --git a/testsuite/tests/th/T8759.stderr b/testsuite/tests/th/T8759.stderr index 3b5474b1ae..b980c00293 100644 --- a/testsuite/tests/th/T8759.stderr +++ b/testsuite/tests/th/T8759.stderr @@ -1,3 +1,3 @@ -T8759.hs:9:4: - Can't represent pattern synonyms in Template Haskell: P +T8759.hs:9:4: warning: + PatSynI T8759.P (ForallT [] [] (ForallT [] [] (TupleT 0))) diff --git a/testsuite/tests/th/T8761.hs b/testsuite/tests/th/T8761.hs new file mode 100644 index 0000000000..4578822904 --- /dev/null +++ b/testsuite/tests/th/T8761.hs @@ -0,0 +1,111 @@ +{-# LANGUAGE TemplateHaskell, RankNTypes, GADTs, PatternSynonyms #-} + +module T8761 where + +{- Testsuite for pattern synonyms as implemented by ticket #8761 -} + +import Control.Monad +import Language.Haskell.TH + +data Ex where MkEx :: forall a. a -> Ex +data ExProv where MkExProv :: forall a. (Show a) => a -> ExProv +data UnivProv a where MkUnivProv :: forall a. (Show a) => a -> UnivProv a + +{- Test manual construction and pretty printing of pattern synonyms -} +do + [qx1,qy1,qz1] <- mapM (\i -> newName $ "x" ++ show i) [1,2,3] + let nm1 = mkName "Q1" + prefixPat = patSynD nm1 (prefixPatSyn [qx1,qy1,qz1]) unidir + (tupP [tupP [varP qx1, varP qy1], listP [varP qz1], wildP, wildP]) + + [qx2,qy2] <- mapM (\i -> newName $ "x" ++ show i) [1,2] + let nm2 = mkName "Q2" + infixPat = patSynD nm2 (infixPatSyn qx2 qy2) implBidir + (tupP [tupP [varP qx2, varP qy2]]) + + let nm3 = mkName "Q3" + [qx3,qy3,qz3] = map mkName ["qx3", "qy3", "qz3"] + patP = tupP [tupP [varP qx3, varP qy3], listP [varP qz3]] + patE = tupE [tupE [varE qx3, varE qy3], listE [varE qz3]] + cls = clause [varP qx3, varP qy3, varP qz3] (normalB patE) [] + recordPat = patSynD nm3 (recordPatSyn [qx3,qy3,qz3]) + (explBidir [cls]) patP + + pats <- sequence [prefixPat, infixPat, recordPat] + -- pretty print the pattern synonyms: + mapM_ (runIO . putStrLn . pprint) pats + -- splice in the pattern synonyms + return pats + +{- Test prefix pattern synonyms -} +[d| + pattern P1 x y z <- ((x,y), [z], _, _) -- unidirectional pattern + pattern P2 x y z = ((x,y), [z]) -- implicit bidirectional pattern + pattern P3 x y z <- ((x,y), [z]) where -- explicit bidirectional pattern + P3 x y z = ((x,y), [z]) |] + +{- Test infix pattern synonyms -} +[d| + pattern x :*: y <- ((x,_), [y]) + pattern x :+: y = (x,y) + pattern x :~: y <- (x,y) where + x :~: y = (x,y) |] + +{- Test record pattern synonyms -} +[d| + pattern R1 {x1, y1} <- ((x1,_), [y1]) + getX1 = x1 ((1, 2), [3]) -- should yield 1 + getY1 = y1 ((1, 2), [3]) -- should yield 3 + pattern R2 {x2, y2} = (x2, [y2]) + pattern R3 {x3, y3} <- (x3, [y3]) where + R3 x y = (x, [y]) |] + +--x1 = "no, no, no" +--y1 = "no, no, no" + +getX1' = x1 ((1, 2), [3]) -- should yield 1 +getY1' = y1 ((1, 2), [3]) -- should yield 3 + +{- Test splicing unidirectional pattern synonyms with different types -} +[d| + pattern P :: Bool + pattern P <- True + + pattern Pe :: () => forall a. a -> Ex + pattern Pe x <- MkEx x + + pattern Pu :: forall a. a -> a + pattern Pu x <- x + + pattern Pue :: forall a. () => forall b. a -> b -> (a, Ex) + pattern Pue x y <- (x, MkEx y) + + pattern Pur :: forall a. (Num a, Eq a) => a -> [a] + pattern Pur x <- [x, 1] + + pattern Purp :: forall a b. (Num a, Eq a) => + Show b => a -> b -> ([a], UnivProv b) + pattern Purp x y <- ([x, 1], MkUnivProv y) + + pattern Pure :: forall a. (Num a, Eq a) => forall b. a -> b -> ([a], Ex) + pattern Pure x y <- ([x, 1], MkEx y) + + pattern Purep :: forall a. (Num a, Eq a) => + forall b. Show b => a -> b -> ([a], ExProv) + pattern Purep x y <- ([x, 1], MkExProv y) + + pattern Pep :: () => forall a. Show a => a -> ExProv + pattern Pep x <- MkExProv x + + pattern Pup :: forall a. () => Show a => a -> UnivProv a + pattern Pup x <- MkUnivProv x + + pattern Puep :: forall a. () => forall b. (Show b) => a -> b -> (ExProv, a) + pattern Puep x y <- (MkExProv y, x) |] + +{- Test reification of different pattern synonyms and their types -} +do + infos <- mapM reify [ 'P, 'Pe, 'Pu, 'Pue, 'Pur, 'Purp + , 'Pure, 'Purep, 'Pep, 'Pup, 'Puep ] + mapM_ (runIO . putStrLn . pprint) infos + [d| theAnswerIs = 42 |] diff --git a/testsuite/tests/th/T8761.stderr b/testsuite/tests/th/T8761.stderr new file mode 100644 index 0000000000..4b3a90c2a2 --- /dev/null +++ b/testsuite/tests/th/T8761.stderr @@ -0,0 +1,158 @@ +pattern Q1 x1_0 x2_1 x3_2 <- ((x1_0, x2_1), [x3_2], _, _) +pattern x1_0 Q2 x2_1 = ((x1_0, x2_1)) +pattern Q3 {qx3, qy3, qz3} <- ((qx3, qy3), [qz3]) where + Q3 qx3 qy3 qz3 = ((qx3, qy3), [qz3]) +T8761.hs:(15,1)-(38,13): Splicing declarations + do { [qx1, qy1, qz1] <- mapM + (\ i -> newName $ "x" ++ show i) [1, 2, 3]; + let nm1 = mkName "Q1" + prefixPat + = patSynD + nm1 + (prefixPatSyn [qx1, qy1, qz1]) + unidir + (tupP [tupP [varP qx1, varP qy1], listP [varP qz1], wildP, wildP]); + [qx2, qy2] <- mapM (\ i -> newName $ "x" ++ show i) [1, 2]; + let nm2 = mkName "Q2" + infixPat + = patSynD + nm2 + (infixPatSyn qx2 qy2) + implBidir + (tupP [tupP [varP qx2, varP qy2]]); + let nm3 = mkName "Q3" + [qx3, qy3, qz3] = map mkName ["qx3", "qy3", "qz3"] + patP = tupP [tupP [varP qx3, varP qy3], listP [varP qz3]] + patE = tupE [tupE [varE qx3, varE qy3], listE [varE qz3]] + cls = clause [varP qx3, varP qy3, varP qz3] (normalB patE) [] + recordPat + = patSynD + nm3 (recordPatSyn [qx3, qy3, qz3]) (explBidir [cls]) patP; + pats <- sequence [prefixPat, infixPat, recordPat]; + mapM_ (runIO . putStrLn . pprint) pats; + return pats } + ======> + pattern Q1 x1 x2 x3 <- ((x1, x2), [x3], _, _) + pattern x1 `Q2` x2 = ((x1, x2)) + pattern Q3{qx3, qy3, qz3} <- ((qx3, qy3), [qz3]) where + Q3 qx3 qy3 qz3 = ((qx3, qy3), [qz3]) +T8761.hs:(41,1)-(45,29): Splicing declarations + [d| pattern P1 x y z <- ((x, y), [z], _, _) + pattern P2 x y z = ((x, y), [z]) + pattern P3 x y z <- ((x, y), [z]) where + P3 x y z = ((x, y), [z]) |] + ======> + pattern P1 x y z <- ((x, y), [z], _, _) + pattern P2 x y z = ((x, y), [z]) + pattern P3 x y z <- ((x, y), [z]) where + P3 x y z = ((x, y), [z]) +T8761.hs:(48,1)-(52,21): Splicing declarations + [d| pattern x :*: y <- ((x, _), [y]) + pattern x :+: y = (x, y) + pattern x :~: y <- (x, y) where + (:~:) x y = (x, y) |] + ======> + pattern x :*: y <- ((x, _), [y]) + pattern x :+: y = (x, y) + pattern x :~: y <- (x, y) where + (:~:) x y = (x, y) +T8761.hs:(55,1)-(61,23): Splicing declarations + [d| pattern R1{x1, y1} <- ((x1, _), [y1]) + getX1 = x1 ((1, 2), [3]) + getY1 = y1 ((1, 2), [3]) + pattern R2{x2, y2} = (x2, [y2]) + pattern R3{x3, y3} <- (x3, [y3]) where + R3 x y = (x, [y]) |] + ======> + pattern R1{x1, y1} <- ((x1, _), [y1]) + getX1 = x1 ((1, 2), [3]) + getY1 = y1 ((1, 2), [3]) + pattern R2{x2, y2} = (x2, [y2]) + pattern R3{x3, y3} <- (x3, [y3]) where + R3 x y = (x, [y]) +T8761.hs:(70,1)-(104,39): Splicing declarations + [d| pattern P :: Bool + pattern P <- True + pattern Pe :: forall a. a -> Ex + pattern Pe x <- MkEx x + pattern Pu :: forall a. a -> a + pattern Pu x <- x + pattern Pue :: forall a. forall b. a -> b -> (a, Ex) + pattern Pue x y <- (x, MkEx y) + pattern Pur :: forall a. (Num a, Eq a) => a -> [a] + pattern Pur x <- [x, 1] + pattern Purp :: forall a b. + (Num a, Eq a) => Show b => a -> b -> ([a], UnivProv b) + pattern Purp x y <- ([x, 1], MkUnivProv y) + pattern Pure :: forall a. + (Num a, Eq a) => forall b. a -> b -> ([a], Ex) + pattern Pure x y <- ([x, 1], MkEx y) + pattern Purep :: forall a. + (Num a, Eq a) => forall b. Show b => a -> b -> ([a], ExProv) + pattern Purep x y <- ([x, 1], MkExProv y) + pattern Pep :: forall a. Show a => a -> ExProv + pattern Pep x <- MkExProv x + pattern Pup :: forall a. Show a => a -> UnivProv a + pattern Pup x <- MkUnivProv x + pattern Puep :: forall a. + forall b. (Show b) => a -> b -> (ExProv, a) + pattern Puep x y <- (MkExProv y, x) |] + ======> + pattern P :: Bool + pattern P <- True + pattern Pe :: forall a. a -> Ex + pattern Pe x <- MkEx x + pattern Pu :: forall a. a -> a + pattern Pu x <- x + pattern Pue :: forall a. forall b. a -> b -> (a, Ex) + pattern Pue x y <- (x, MkEx y) + pattern Pur :: forall a. (Num a, Eq a) => a -> [a] + pattern Pur x <- [x, 1] + pattern Purp :: forall a b. + (Num a, Eq a) => Show b => a -> b -> ([a], UnivProv b) + pattern Purp x y <- ([x, 1], MkUnivProv y) + pattern Pure :: forall a. + (Num a, Eq a) => forall b. a -> b -> ([a], Ex) + pattern Pure x y <- ([x, 1], MkEx y) + pattern Purep :: forall a. + (Num a, Eq a) => forall b. Show b => a -> b -> ([a], ExProv) + pattern Purep x y <- ([x, 1], MkExProv y) + pattern Pep :: forall a. Show a => a -> ExProv + pattern Pep x <- MkExProv x + pattern Pup :: forall a. Show a => a -> UnivProv a + pattern Pup x <- MkUnivProv x + pattern Puep :: forall a. forall b. Show b => a -> b -> (ExProv, a) + pattern Puep x y <- (MkExProv y, x) +pattern T8761.P :: GHC.Types.Bool +pattern T8761.Pe :: () => forall (a0_0 :: *) . a0_0 -> T8761.Ex +pattern T8761.Pu :: forall (a0_0 :: *) . a0_0 -> a0_0 +pattern T8761.Pue :: forall (a0_0 :: *) . () => forall (b0_1 :: *) . + a0_0 -> b0_1 -> (a0_0, T8761.Ex) +pattern T8761.Pur :: forall (a0_0 :: *) . (GHC.Num.Num a0_0, + GHC.Classes.Eq a0_0) => + a0_0 -> [a0_0] +pattern T8761.Purp :: forall (a0_0 :: *) (b0_1 :: *) . (GHC.Num.Num a0_0, + GHC.Classes.Eq a0_0) => + GHC.Show.Show b0_1 => a0_0 -> b0_1 -> ([a0_0], T8761.UnivProv b0_1) +pattern T8761.Pure :: forall (a0_0 :: *) . (GHC.Num.Num a0_0, + GHC.Classes.Eq a0_0) => + forall (b0_1 :: *) . a0_0 -> b0_1 -> ([a0_0], T8761.Ex) +pattern T8761.Purep :: forall (a0_0 :: *) . (GHC.Num.Num a0_0, + GHC.Classes.Eq a0_0) => + forall (b0_1 :: *) . GHC.Show.Show b0_1 => + a0_0 -> b0_1 -> ([a0_0], T8761.ExProv) +pattern T8761.Pep :: () => forall (a0_0 :: *) . GHC.Show.Show a0_0 => + a0_0 -> T8761.ExProv +pattern T8761.Pup :: forall (a0_0 :: *) . () => GHC.Show.Show a0_0 => + a0_0 -> T8761.UnivProv a0_0 +pattern T8761.Puep :: forall (a0_0 :: *) . () => forall (b0_1 :: *) . GHC.Show.Show b0_1 => + a0_0 -> b0_1 -> (T8761.ExProv, a0_0) +T8761.hs:(107,1)-(111,25): Splicing declarations + do { infos <- mapM + reify + ['P, 'Pe, 'Pu, 'Pue, 'Pur, 'Purp, 'Pure, 'Purep, 'Pep, 'Pup, + 'Puep]; + mapM_ (runIO . putStrLn . pprint) infos; + [d| theAnswerIs = 42 |] } + ======> + theAnswerIs = 42 diff --git a/testsuite/tests/th/T9064.stderr b/testsuite/tests/th/T9064.stderr index 24fdc8da83..f118e202ad 100644 --- a/testsuite/tests/th/T9064.stderr +++ b/testsuite/tests/th/T9064.stderr @@ -1,6 +1,5 @@ class T9064.C (a_0 :: *) where T9064.foo :: forall (a_0 :: *) . T9064.C a_0 => - a_0 -> GHC.Base.String - default T9064.foo :: forall . GHC.Show.Show a_0 => - a_0 -> GHC.Base.String + a_0 -> GHC.Base.String + default T9064.foo :: GHC.Show.Show a_0 => a_0 -> GHC.Base.String instance T9064.C T9064.Bar diff --git a/testsuite/tests/th/all.T b/testsuite/tests/th/all.T index a69f8a7413..be6828fe4d 100644 --- a/testsuite/tests/th/all.T +++ b/testsuite/tests/th/all.T @@ -322,7 +322,7 @@ test('T8625', normal, ghci_script, ['T8625.script']) test('TH_StaticPointers', [when(doing_ghci(), extra_hc_opts('-fobject-code'))], compile_and_run, ['']) test('TH_StaticPointers02', [], compile_fail, ['']) -test('T8759', normal, compile_fail, ['-v0']) +test('T8759', normal, compile, ['-v0']) test('T7021', extra_clean(['T7021a.hi', 'T7021a.o']), multimod_compile, ['T7021','-v0 ' + config.ghc_th_way_flags]) @@ -393,7 +393,6 @@ test('T10819', test('T10820', normal, compile_and_run, ['-v0']) test('T11341', normal, compile, ['-v0 -dsuppress-uniques']) test('T11345', normal, compile_and_run, ['-v0 -dsuppress-uniques']) - test('TH_finalizer', normal, compile, ['-v0']) test('T10603', normal, compile, ['-ddump-splices -dsuppress-uniques']) test('T11452', normal, compile_fail, ['-v0']) @@ -405,3 +404,4 @@ test('T11809', normal, compile, ['-v0']) test('T11797', normal, compile, ['-v0 -dsuppress-uniques']) test('T11941', normal, compile_fail, ['-v0']) test('T11484', normal, compile, ['-v0']) +test('T8761', normal, compile, ['-v0 -ddump-splices -dsuppress-uniques']) |