Commit 708c60aa authored by Ryan Scott's avatar Ryan Scott Committed by Marge Bot

Clean up TH's treatment of unary tuples (or, #16881 part two)

!1906 left some loose ends in regards to Template Haskell's treatment
of unary tuples. This patch ends to tie up those loose ends:

* In addition to having `TupleT 1` produce unary tuples, `TupE [exp]`
  and `TupP [pat]` also now produce unary tuples.
* I have added various special cases in GHC's pretty-printers to
  ensure that explicit 1-tuples are printed using the `Unit` type.
  See `testsuite/tests/th/T17380`.
* The GHC 8.10.1 release notes entry has been tidied up a little.

Fixes #16881. Fixes #17371. Fixes #17380.
parent b4fb2328
......@@ -13,6 +13,7 @@
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
-- | Abstract Haskell syntax for expressions.
module GHC.Hs.Expr where
......@@ -43,6 +44,7 @@ import Util
import Outputable
import FastString
import Type
import TysWiredIn (mkTupleStr)
import TcType (TcType)
import {-# SOURCE #-} TcRnTypes (TcLclEnv)
......@@ -908,6 +910,12 @@ ppr_expr (SectionR _ op expr)
pp_infixly v = sep [v, pp_expr]
ppr_expr (ExplicitTuple _ exprs boxity)
-- Special-case unary boxed tuples so that they are pretty-printed as
-- `Unit x`, not `(x)`
| [dL -> L _ (Present _ expr)] <- exprs
, Boxed <- boxity
= hsep [text (mkTupleStr Boxed 1), ppr expr]
| otherwise
= tupleParens (boxityTupleSort boxity) (fcat (ppr_tup_args $ map unLoc exprs))
where
ppr_tup_args [] = []
......
......@@ -529,8 +529,14 @@ pprPat (CoPat _ co pat _) = pprHsWrapper co $ \parens
else pprPat pat
pprPat (SigPat _ pat ty) = ppr pat <+> dcolon <+> ppr ty
pprPat (ListPat _ pats) = brackets (interpp'SP pats)
pprPat (TuplePat _ pats bx) = tupleParens (boxityTupleSort bx)
(pprWithCommas ppr pats)
pprPat (TuplePat _ pats bx)
-- Special-case unary boxed tuples so that they are pretty-printed as
-- `Unit x`, not `(x)`
| [pat] <- pats
, Boxed <- bx
= hcat [text (mkTupleStr Boxed 1), pprParendLPat appPrec pat]
| otherwise
= tupleParens (boxityTupleSort bx) (pprWithCommas ppr pats)
pprPat (SumPat _ pat alt arity) = sumParens (pprAlternative ppr pat alt arity)
pprPat (ConPatIn con details) = pprUserCon (unLoc con) details
pprPat (ConPatOut { pat_con = con
......
......@@ -85,6 +85,7 @@ import RdrName ( RdrName )
import DataCon( HsSrcBang(..), HsImplBang(..),
SrcStrictness(..), SrcUnpackedness(..) )
import TysPrim( funTyConName )
import TysWiredIn( mkTupleStr )
import Type
import GHC.Hs.Doc
import BasicTypes
......@@ -1600,7 +1601,14 @@ ppr_mono_ty (HsTyVar _ prom (L _ name))
| isPromoted prom = quote (pprPrefixOcc name)
| otherwise = pprPrefixOcc name
ppr_mono_ty (HsFunTy _ ty1 ty2) = ppr_fun_ty ty1 ty2
ppr_mono_ty (HsTupleTy _ con tys) = tupleParens std_con (pprWithCommas ppr tys)
ppr_mono_ty (HsTupleTy _ con tys)
-- Special-case unary boxed tuples so that they are pretty-printed as
-- `Unit x`, not `(x)`
| [ty] <- tys
, BoxedTuple <- std_con
= sep [text (mkTupleStr Boxed 1), ppr_mono_lty ty]
| otherwise
= tupleParens std_con (pprWithCommas ppr tys)
where std_con = case con of
HsUnboxedTuple -> UnboxedTuple
_ -> BoxedTuple
......@@ -1615,6 +1623,11 @@ ppr_mono_ty (HsExplicitListTy _ prom tys)
| isPromoted prom = quote $ brackets (maybeAddSpace tys $ interpp'SP tys)
| otherwise = brackets (interpp'SP tys)
ppr_mono_ty (HsExplicitTupleTy _ tys)
-- Special-case unary boxed tuples so that they are pretty-printed as
-- `'Unit x`, not `'(x)`
| [ty] <- tys
= quote $ sep [text (mkTupleStr Boxed 1), ppr_mono_lty ty]
| otherwise
= quote $ parens (maybeAddSpace tys $ interpp'SP tys)
ppr_mono_ty (HsTyLit _ t) = ppr_tylit t
ppr_mono_ty (HsWildCardTy {}) = char '_'
......
......@@ -908,9 +908,6 @@ cvtl e = wrapL (cvt e)
; return $ HsLamCase noExtField
(mkMatchGroup FromSource ms')
}
cvt (TupE [Just e]) = do { e' <- cvtl e; return $ HsPar noExtField e' }
-- Note [Dropping constructors]
-- Singleton tuples treated like nothing (just parens)
cvt (TupE es) = cvt_tup es Boxed
cvt (UnboxedTupE es) = cvt_tup es Unboxed
cvt (UnboxedSumE e alt arity) = do { e' <- cvtl e
......@@ -1018,14 +1015,13 @@ ensureValidOpExp _e _m =
{- Note [Dropping constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we drop constructors from the input (for instance, when we encounter @TupE [e]@)
we must insert parentheses around the argument. Otherwise, @UInfix@ constructors in @e@
could meet @UInfix@ constructors containing the @TupE [e]@. For example:
When we drop constructors from the input, we must insert parentheses around the
argument. For example:
UInfixE x * (TupE [UInfixE y + z])
UInfixE x * (AppE (InfixE (Just y) + Nothing) z)
If we drop the singleton tuple but don't insert parentheses, the @UInfixE@s would meet
and the above expression would be reassociated to
If we convert the InfixE expression to an operator section but don't insert
parentheses, the above expression would be reassociated to
OpApp (OpApp x * y) + z
......@@ -1254,8 +1250,6 @@ cvtp (TH.LitP l)
| otherwise = do { l' <- cvtLit l; return $ Hs.LitPat noExtField l' }
cvtp (TH.VarP s) = do { s' <- vName s
; return $ Hs.VarPat noExtField (noLoc s') }
cvtp (TupP [p]) = do { p' <- cvtPat p; return $ ParPat noExtField p' }
-- Note [Dropping constructors]
cvtp (TupP ps) = do { ps' <- cvtPats ps
; return $ TuplePat noExtField ps' Boxed }
cvtp (UnboxedTupP ps) = do { ps' <- cvtPats ps
......
......@@ -62,7 +62,7 @@ module IfaceType (
import GhcPrelude
import {-# SOURCE #-} TysWiredIn ( coercibleTyCon, heqTyCon
, liftedRepDataConTyCon )
, liftedRepDataConTyCon, tupleTyConName )
import {-# SOURCE #-} TyCoRep ( isRuntimeRepTy )
import DynFlags
......@@ -1466,30 +1466,47 @@ pprSum _arity is_promoted args
<> sumParens (pprWithBars (ppr_ty topPrec) args')
pprTuple :: PprPrec -> TupleSort -> PromotionFlag -> IfaceAppArgs -> SDoc
pprTuple ctxt_prec ConstraintTuple NotPromoted IA_Nil
= maybeParen ctxt_prec sigPrec $
text "() :: Constraint"
pprTuple ctxt_prec sort promoted args =
case promoted of
IsPromoted
-> let tys = appArgsIfaceTypes args
args' = drop (length tys `div` 2) tys
spaceIfPromoted = case args' of
arg0:_ -> pprSpaceIfPromotedTyCon arg0
_ -> id
in ppr_tuple_app args' $
pprPromotionQuoteI IsPromoted <>
tupleParens sort (spaceIfPromoted (pprWithCommas pprIfaceType args'))
NotPromoted
| ConstraintTuple <- sort
, IA_Nil <- args
-> maybeParen ctxt_prec sigPrec $
text "() :: Constraint"
-- All promoted constructors have kind arguments
pprTuple _ sort IsPromoted args
= let tys = appArgsIfaceTypes args
args' = drop (length tys `div` 2) tys
spaceIfPromoted = case args' of
arg0:_ -> pprSpaceIfPromotedTyCon arg0
_ -> id
in pprPromotionQuoteI IsPromoted <>
tupleParens sort (spaceIfPromoted (pprWithCommas pprIfaceType args'))
pprTuple _ sort promoted args
= -- drop the RuntimeRep vars.
-- See Note [Unboxed tuple RuntimeRep vars] in TyCon
let tys = appArgsIfaceTypes args
args' = case sort of
UnboxedTuple -> drop (length tys `div` 2) tys
_ -> tys
in
pprPromotionQuoteI promoted <>
tupleParens sort (pprWithCommas pprIfaceType args')
| otherwise
-> -- drop the RuntimeRep vars.
-- See Note [Unboxed tuple RuntimeRep vars] in TyCon
let tys = appArgsIfaceTypes args
args' = case sort of
UnboxedTuple -> drop (length tys `div` 2) tys
_ -> tys
in
ppr_tuple_app args' $
pprPromotionQuoteI promoted <>
tupleParens sort (pprWithCommas pprIfaceType args')
where
ppr_tuple_app :: [IfaceType] -> SDoc -> SDoc
ppr_tuple_app args_wo_runtime_reps ppr_args_w_parens
-- Special-case unary boxed tuples so that they are pretty-printed as
-- `Unit x`, not `(x)`
| [_] <- args_wo_runtime_reps
, BoxedTuple <- sort
= let unit_tc_info = IfaceTyConInfo promoted IfaceNormalTyCon
unit_tc = IfaceTyCon (tupleTyConName sort 1) unit_tc_info in
pprPrecIfaceType ctxt_prec $ IfaceTyConApp unit_tc args
| otherwise
= ppr_args_w_parens
pprIfaceTyLit :: IfaceTyLit -> SDoc
pprIfaceTyLit (IfaceNumTyLit n) = integer n
......
......@@ -68,7 +68,7 @@ module TysWiredIn (
justDataCon, justDataConName, promotedJustDataCon,
-- * Tuples
mkTupleTy, mkTupleTy1, mkBoxedTupleTy,
mkTupleTy, mkTupleTy1, mkBoxedTupleTy, mkTupleStr,
tupleTyCon, tupleDataCon, tupleTyConName,
promotedTupleDataCon,
unitTyCon, unitDataCon, unitDataConId, unitTy, unitTyConKey,
......@@ -783,6 +783,10 @@ mkTupleOcc ns Unboxed ar = mkOccName ns (mkUnboxedTupleStr ar)
mkCTupleOcc :: NameSpace -> Arity -> OccName
mkCTupleOcc ns ar = mkOccName ns (mkConstraintTupleStr ar)
mkTupleStr :: Boxity -> Arity -> String
mkTupleStr Boxed = mkBoxedTupleStr
mkTupleStr Unboxed = mkUnboxedTupleStr
mkBoxedTupleStr :: Arity -> String
mkBoxedTupleStr 0 = "()"
mkBoxedTupleStr 1 = "Unit" -- See Note [One-tuples]
......
......@@ -3,6 +3,9 @@ module TysWiredIn where
import {-# SOURCE #-} TyCon ( TyCon )
import {-# SOURCE #-} TyCoRep (Type, Kind)
import BasicTypes (Arity, TupleSort)
import Name (Name)
listTyCon :: TyCon
typeNatKind, typeSymbolKind :: Type
mkBoxedTupleTy :: [Type] -> Type
......@@ -38,3 +41,5 @@ int8ElemRepDataConTy, int16ElemRepDataConTy, int32ElemRepDataConTy,
anyTypeOfKind :: Kind -> Type
unboxedTupleKind :: [Type] -> Type
mkPromotedListTy :: Type -> [Type] -> Type
tupleTyConName :: TupleSort -> Arity -> Name
......@@ -219,9 +219,12 @@ Template Haskell
:extension:`DeriveLift` has been simplified to take advantage of expression
quotations.
- Explicit boxed 1-tuples from ``HsSyn`` are now treated as actual 1-tuples,
without flattening. In most of the cases these will be obtained using
Template Haskell since it is uncommon to deal with 1-tuples in the source.
- Using ``TupleT 1``, ``TupE [exp]``, or ``TupP [pat]`` will now produce unary
tuples (i.e., involving the ``Unit`` type from ``GHC.Tuple``) instead of
silently dropping the parentheses. This brings Template Haskell's treatment
of boxed tuples in line with that of unboxed tuples, as ``UnboxedTupleT`,
``UnboxedTupE``, and ``UnboxedTupP`` also produce unary unboxed tuples
(i.e., ``Unit#``) when applied to only one argument.
- GHC's constraint solver now solves constraints in each top-level group
sooner. This has practical consequences for Template Haskell, as TH splices
......
......@@ -153,7 +153,11 @@ pprExp i (LamE ps e) = parensIf (i > noPrec) $ char '\\' <> hsep (map (pprPat ap
<+> text "->" <+> ppr e
pprExp i (LamCaseE ms) = parensIf (i > noPrec)
$ text "\\case" $$ nest nestDepth (ppr ms)
pprExp _ (TupE es) = parens (commaSepWith (pprMaybeExp noPrec) es)
pprExp i (TupE es)
| [Just e] <- es
= pprExp i (ConE (tupleDataName 1) `AppE` e)
| otherwise
= parens (commaSepWith (pprMaybeExp noPrec) es)
pprExp _ (UnboxedTupE es) = hashParens (commaSepWith (pprMaybeExp noPrec) es)
pprExp _ (UnboxedSumE e alt arity) = unboxedSumBars (ppr e) alt arity
-- Nesting in Cond is to avoid potential problems in do statements
......@@ -291,7 +295,11 @@ instance Ppr Pat where
pprPat :: Precedence -> Pat -> Doc
pprPat i (LitP l) = pprLit i l
pprPat _ (VarP v) = pprName' Applied v
pprPat _ (TupP ps) = parens (commaSep ps)
pprPat i (TupP ps)
| [_] <- ps
= pprPat i (ConP (tupleDataName 1) ps)
| otherwise
= parens (commaSep ps)
pprPat _ (UnboxedTupP ps) = hashParens (commaSep ps)
pprPat _ (UnboxedSumP p alt arity) = unboxedSumBars (ppr p) alt arity
pprPat i (ConP s ps) = parensIf (i >= appPrec) $ pprName' Applied s
......@@ -742,6 +750,7 @@ pprParendType (VarT v) = pprName' Applied v
-- `Applied` is used here instead of `ppr` because of infix names (#13887)
pprParendType (ConT c) = pprName' Applied c
pprParendType (TupleT 0) = text "()"
pprParendType (TupleT 1) = pprParendType (ConT (tupleTypeName 1))
pprParendType (TupleT n) = parens (hcat (replicate (n-1) comma))
pprParendType (UnboxedTupleT n) = hashParens $ hcat $ replicate (n-1) comma
pprParendType (UnboxedSumT arity) = hashParens $ hcat $ replicate (arity-1) bar
......@@ -750,6 +759,7 @@ pprParendType ListT = text "[]"
pprParendType (LitT l) = pprTyLit l
pprParendType (PromotedT c) = text "'" <> pprName' Applied c
pprParendType (PromotedTupleT 0) = text "'()"
pprParendType (PromotedTupleT 1) = pprParendType (PromotedT (tupleDataName 1))
pprParendType (PromotedTupleT n) = quoteParens (hcat (replicate (n-1) comma))
pprParendType PromotedNilT = text "'[]"
pprParendType PromotedConsT = text "'(:)"
......@@ -801,9 +811,15 @@ pprTyApp (EqualityT, [TANormal arg1, TANormal arg2]) =
sep [pprFunArgType arg1 <+> text "~", ppr arg2]
pprTyApp (ListT, [TANormal arg]) = brackets (ppr arg)
pprTyApp (TupleT n, args)
| length args == n = parens (commaSep args)
| length args == n
= if n == 1
then pprTyApp (ConT (tupleTypeName 1), args)
else parens (commaSep args)
pprTyApp (PromotedTupleT n, args)
| length args == n = quoteParens (commaSep args)
| length args == n
= if n == 1
then pprTyApp (PromotedT (tupleDataName 1), args)
else quoteParens (commaSep args)
pprTyApp (fun, args) = pprParendType fun <+> sep (map pprParendTypeArg args)
pprFunArgType :: Type -> Doc -- Should really use a precedence argument
......
[(AnnotationTuple.hs:14:20, [p], (1)),
(AnnotationTuple.hs:14:23-29, [p], ("hello")),
(AnnotationTuple.hs:14:35-37, [p], (6.5)),
[(AnnotationTuple.hs:14:20, [p], Unit 1),
(AnnotationTuple.hs:14:23-29, [p], Unit "hello"),
(AnnotationTuple.hs:14:35-37, [p], Unit 6.5),
(AnnotationTuple.hs:14:39, [m], ()),
(AnnotationTuple.hs:14:41-52, [p], ([5, 5, 6, 7])),
(AnnotationTuple.hs:16:8, [p], (1)),
(AnnotationTuple.hs:16:11-17, [p], ("hello")),
(AnnotationTuple.hs:16:20-22, [p], (6.5)),
(AnnotationTuple.hs:14:41-52, [p], Unit [5, 5, 6, 7]),
(AnnotationTuple.hs:16:8, [p], Unit 1),
(AnnotationTuple.hs:16:11-17, [p], Unit "hello"),
(AnnotationTuple.hs:16:20-22, [p], Unit 6.5),
(AnnotationTuple.hs:16:24, [m], ()),
(AnnotationTuple.hs:16:25, [m], ()),
(AnnotationTuple.hs:16:26, [m], ()), (<no location info>, [m], ())]
......
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Language.Haskell.TH
foo :: String -> $(tupleT 1 `appT` conT ''String)
foo x = $(tupE [[| x |]])
bar :: $(tupleT 1 `appT` conT ''String) -> String
bar $(tupP [[p| x |]]) = x
main :: IO ()
main = do
foo undefined `seq` putStrLn "hello"
putStrLn $ bar $ foo "world"
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
module T17380 where
import Data.Proxy
import Language.Haskell.TH
foo :: $(tupleT 1 `appT` (conT ''Maybe `appT` conT ''String))
foo = Just "wat"
bar :: Maybe String
bar = $(tupE [[| Just "wat" |]])
baz :: $(tupleT 1 `appT` (conT ''Maybe `appT` conT ''String)) -> Maybe String
baz (Just "wat") = Just "frerf"
quux :: Maybe String -> Maybe String
quux $(tupP [[p| Just "wat" |]]) = Just "frerf"
quuz :: Proxy $(promotedTupleT 1 `appT` (conT ''Maybe `appT` conT ''String))
quuz = Proxy :: Proxy (Maybe String)
fred :: Proxy (Maybe String)
fred = Proxy :: Proxy $(promotedTupleT 1 `appT` (conT ''Maybe `appT` conT ''String))
T17380.hs:9:7: error:
• Couldn't match expected type ‘Unit (Maybe String)’
with actual type ‘Maybe [Char]’
• In the expression: Just "wat"
In an equation for ‘foo’: foo = Just "wat"
T17380.hs:12:9: error:
• Couldn't match expected type ‘Maybe String’
with actual type ‘Unit (Maybe [Char])’
• In the expression: (Unit Just "wat")
In an equation for ‘bar’: bar = (Unit Just "wat")
T17380.hs:15:6: error:
• Couldn't match expected type ‘Unit (Maybe String)’
with actual type ‘Maybe [Char]’
• In the pattern: Just "wat"
In an equation for ‘baz’: baz (Just "wat") = Just "frerf"
T17380.hs:18:8: error:
• Couldn't match expected type ‘Maybe String’
with actual type ‘Unit (Maybe [Char])’
• In the pattern: Unit(Just "wat")
In an equation for ‘quux’: quux (Unit(Just "wat")) = Just "frerf"
T17380.hs:21:8: error:
• Couldn't match type ‘Maybe String’ with ‘'Unit (Maybe String)’
Expected type: Proxy ('Unit (Maybe String))
Actual type: Proxy (Maybe String)
• In the expression: Proxy :: Proxy (Maybe String)
In an equation for ‘quuz’: quuz = Proxy :: Proxy (Maybe String)
T17380.hs:24:8: error:
• Couldn't match type ‘'Unit (Maybe String)’ with ‘Maybe String’
Expected type: Proxy (Maybe String)
Actual type: Proxy ('Unit (Maybe String))
• In the expression: Proxy :: Proxy ('Unit Maybe String)
In an equation for ‘fred’:
fred = Proxy :: Proxy ('Unit Maybe String)
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 x1_0 Q2 x2_1 = GHC.Tuple.Unit (x1_0, x2_1)
pattern Q3 {qx3, qy3, qz3} <- ((qx3, qy3), [qz3]) where
Q3 qx3 qy3 qz3 = ((qx3, qy3), [qz3])
T8761.hs:(16,1)-(39,13): Splicing declarations
......@@ -8,17 +8,13 @@ T8761.hs:(16,1)-(39,13): Splicing declarations
let nm1 = mkName "Q1"
prefixPat
= patSynD
nm1
(prefixPatSyn [qx1, qy1, qz1])
unidir
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
nm2 (infixPatSyn qx2 qy2) implBidir
(tupP [tupP [varP qx2, varP qy2]])
let nm3 = mkName "Q3"
[qx3, qy3, qz3] = map mkName ["qx3", "qy3", "qz3"]
......@@ -32,7 +28,7 @@ T8761.hs:(16,1)-(39,13): Splicing declarations
return pats
======>
pattern Q1 x1 x2 x3 <- ((x1, x2), [x3], _, _)
pattern x1 `Q2` x2 = ((x1, x2))
pattern x1 `Q2` x2 = Unit(x1, x2)
pattern Q3{qx3, qy3, qz3} <- ((qx3, qy3), [qz3]) where
Q3 qx3 qy3 qz3 = ((qx3, qy3), [qz3])
T8761.hs:(42,1)-(46,29): Splicing declarations
......
TH_Promoted1Tuple.hs:7:3: error:
Illegal type: ‘'(Int)’ Perhaps you intended to use DataKinds
Illegal type: ‘'Unit Int’ Perhaps you intended to use DataKinds
......@@ -42,10 +42,7 @@ exprs = [
-------------- Sections
$( infixE (Just $ n +? n) plus Nothing ) N,
-- see B.hs for the (non-compiling) other version of the above
$( infixE Nothing plus (Just $ parensE $ uInfixE n plus n) ) N,
-------------- Dropping constructors
$( n *? tupE [n +? n] )
$( infixE Nothing plus (Just $ parensE $ uInfixE n plus n) ) N
]
--------------------------------------------------------------------------------
......@@ -85,10 +82,7 @@ patterns = [
case (N :+ N) :* (N :+ N) of
[p14|unused|] -> True,
case (N :+ (N :* N)) :+ N of
[p15|unused|] -> True,
-------------- Dropping constructors
case (N :* (N :+ N)) of
[p16|unused|] -> True
[p15|unused|] -> True
]
--------------------------------------------------------------------------------
......
......@@ -19,8 +19,6 @@
((N :+ (N :* N)) :+ N)
((N :+ N) :+ N)
(N :+ (N :+ N))
(N :* (N :+ N))
True
True
True
True
......
......@@ -11,8 +11,8 @@ infixl 6 :+
infixl 7 :*
data Tree = N
| Tree :+ Tree
| Tree :* Tree
| Tree :+ Tree
| Tree :* Tree
-- custom instance, including redundant parentheses
instance Show Tree where
......@@ -73,8 +73,6 @@ p12 = mkQQ ( (p ^+? p) ^*! (p ^+? p) )
p13 = mkQQ ( ((parensP ((p ^+? p) ^*? p)) ^+? p) ^*? p )
p14 = mkQQ ( (parensP (p ^+? p)) ^*? (parensP (p ^+? p)) )
p15 = mkQQ ( parensP ((p ^+? p) ^*? (p ^+? p)) )
-------------- Dropping constructors
p16 = mkQQ ( p ^*? (tupP [p ^+? p]) )
--------------------------------------------------------------------------------
-- Types --
......
......@@ -475,6 +475,7 @@ test('T16293b', normal, compile, [''])
test('T16326_TH', normal, compile, ['-v0 -ddump-splices -dsuppress-uniques'])
test('T14741', normal, compile_and_run, [''])
test('T16666', normal, compile, ['-v0 -ddump-splices -dsuppress-uniques'])
test('T16881', normal, compile_and_run, [''])
test('T16895a', normal, compile_fail, [''])
test('T16895b', normal, compile_fail, [''])
test('T16895c', normal, compile_fail, [''])
......@@ -486,6 +487,7 @@ test('T16976z', normal, compile_fail, [''])
test('T16980', normal, compile, [''])
test('T16980a', normal, compile_fail, [''])
test('T17296', normal, compile, ['-v0'])
test('T17380', normal, compile_fail, [''])
test('T17394', normal, compile, ['-v0 -ddump-splices -dsuppress-uniques'])
test('T17379a', normal, compile_fail, [''])
test('T17379b', normal, compile_fail, [''])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment