[commit: ghc] wip/rae: Fix #9209, by reporting an error instead of panicking on bad splices. (20e1bb1)

git at git.haskell.org git at git.haskell.org
Tue Nov 4 16:36:31 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/rae
Link       : http://ghc.haskell.org/trac/ghc/changeset/20e1bb1c582bd7b884bea624fee8699f3e2ec3d3/ghc

>---------------------------------------------------------------

commit 20e1bb1c582bd7b884bea624fee8699f3e2ec3d3
Author: Richard Eisenberg <eir at cis.upenn.edu>
Date:   Mon Nov 3 13:49:59 2014 -0500

    Fix #9209, by reporting an error instead of panicking on bad splices.


>---------------------------------------------------------------

20e1bb1c582bd7b884bea624fee8699f3e2ec3d3
 compiler/parser/Parser.y.pp  | 15 ++++++------
 compiler/parser/RdrHsSyn.lhs | 57 +++++++++++++++++++++++++-------------------
 testsuite/tests/th/all.T     |  2 +-
 3 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp
index e33808d..98468d4 100644
--- a/compiler/parser/Parser.y.pp
+++ b/compiler/parser/Parser.y.pp
@@ -684,12 +684,12 @@ ty_decl :: { LTyClDecl RdrName }
 
 inst_decl :: { LInstDecl RdrName }
         : 'instance' overlap_pragma inst_type where_inst
-                 { let (binds, sigs, _, ats, adts, _) = cvBindsAndSigs (unLoc $4) in
-                   let cid = ClsInstDecl { cid_poly_ty = $3, cid_binds = binds
-                                         , cid_sigs = sigs, cid_tyfam_insts = ats
-                                         , cid_overlap_mode = $2
-                                         , cid_datafam_insts = adts }
-                   in L (comb3 $1 $3 $4) (ClsInstD { cid_inst = cid }) }
+            {% do { (binds, sigs, _, ats, adts, _) <- cvBindsAndSigs (unLoc $4)
+                  ; let cid = ClsInstDecl { cid_poly_ty = $3, cid_binds = binds
+                                          , cid_sigs = sigs, cid_tyfam_insts = ats
+                                          , cid_overlap_mode = $2
+                                          , cid_datafam_insts = adts }
+                  ; return (L (comb3 $1 $3 $4) (ClsInstD { cid_inst = cid })) } }
 
            -- type instance declarations
         | 'type' 'instance' ty_fam_inst_eqn
@@ -950,7 +950,8 @@ decllist :: { Located (OrdList (LHsDecl RdrName)) }
 --
 binds   ::  { Located (HsLocalBinds RdrName) }          -- May have implicit parameters
                                                 -- No type declarations
-        : decllist                      { L1 (HsValBinds (cvBindGroup (unLoc $1))) }
+        : decllist                      {% do { val_binds <- cvBindGroup (unLoc $1)
+                                              ; return (L1 (HsValBinds val_binds)) } }
         | '{'            dbinds '}'     { LL (HsIPBinds (IPBinds (unLoc $2) emptyTcEvBinds)) }
         |     vocurly    dbinds close   { L (getLoc $2) (HsIPBinds (IPBinds (unLoc $2) emptyTcEvBinds)) }
 
diff --git a/compiler/parser/RdrHsSyn.lhs b/compiler/parser/RdrHsSyn.lhs
index e6969e7..125bfa9 100644
--- a/compiler/parser/RdrHsSyn.lhs
+++ b/compiler/parser/RdrHsSyn.lhs
@@ -127,8 +127,8 @@ mkClassDecl :: SrcSpan
             -> P (LTyClDecl RdrName)
 
 mkClassDecl loc (L _ (mcxt, tycl_hdr)) fds where_cls
-  = do { let (binds, sigs, ats, at_insts, _, docs) = cvBindsAndSigs (unLoc where_cls)
-             cxt = fromMaybe (noLoc []) mcxt
+  = do { (binds, sigs, ats, at_insts, _, docs) <- cvBindsAndSigs (unLoc where_cls)
+       ; let cxt = fromMaybe (noLoc []) mcxt
        ; (cls, tparams) <- checkTyClHdr tycl_hdr
        ; tyvars <- checkTyVarsP (ptext (sLit "class")) whereDots cls tparams
        ; at_defs <- mapM (eitherToP . mkATDefault) at_insts
@@ -308,36 +308,45 @@ cvTopDecls decls = go (fromOL decls)
     go (d : ds)             = d : go ds
 
 -- Declaration list may only contain value bindings and signatures.
-cvBindGroup :: OrdList (LHsDecl RdrName) -> HsValBinds RdrName
+cvBindGroup :: OrdList (LHsDecl RdrName) -> P (HsValBinds RdrName)
 cvBindGroup binding
-  = case cvBindsAndSigs binding of
-      (mbs, sigs, fam_ds, tfam_insts, dfam_insts, _) 
-         -> ASSERT( null fam_ds && null tfam_insts && null dfam_insts)
-            ValBindsIn mbs sigs
+  = do { (mbs, sigs, fam_ds, tfam_insts, dfam_insts, _) <- cvBindsAndSigs binding
+       ; ASSERT( null fam_ds && null tfam_insts && null dfam_insts)
+         return $ ValBindsIn mbs sigs }
 
 cvBindsAndSigs :: OrdList (LHsDecl RdrName)
-  -> (LHsBinds RdrName, [LSig RdrName], [LFamilyDecl RdrName]
+  -> P (LHsBinds RdrName, [LSig RdrName], [LFamilyDecl RdrName]
           , [LTyFamInstDecl RdrName], [LDataFamInstDecl RdrName], [LDocDecl])
 -- Input decls contain just value bindings and signatures
 -- and in case of class or instance declarations also
 -- associated type declarations. They might also contain Haddock comments.
-cvBindsAndSigs  fb = go (fromOL fb)
+cvBindsAndSigs fb = go (fromOL fb)
   where
-    go []                  = (emptyBag, [], [], [], [], [])
-    go (L l (SigD s) : ds) = (bs, L l s : ss, ts, tfis, dfis, docs)
-                           where (bs, ss, ts, tfis, dfis, docs) = go ds
-    go (L l (ValD b) : ds) = (b' `consBag` bs, ss, ts, tfis, dfis, docs)
-                           where (b', ds')    = getMonoBind (L l b) ds
-                                 (bs, ss, ts, tfis, dfis, docs) = go ds'
-    go (L l (TyClD (FamDecl t)) : ds) = (bs, ss, L l t : ts, tfis, dfis, docs)
-                           where (bs, ss, ts, tfis, dfis, docs) = go ds
-    go (L l (InstD (TyFamInstD { tfid_inst = tfi })) : ds) = (bs, ss, ts, L l tfi : tfis, dfis, docs)
-                           where (bs, ss, ts, tfis, dfis, docs) = go ds
-    go (L l (InstD (DataFamInstD { dfid_inst = dfi })) : ds) = (bs, ss, ts, tfis, L l dfi : dfis, docs)
-                           where (bs, ss, ts, tfis, dfis, docs) = go ds
-    go (L l (DocD d) : ds) =  (bs, ss, ts, tfis, dfis, (L l d) : docs)
-                           where (bs, ss, ts, tfis, dfis, docs) = go ds
-    go (L _ d : _) = pprPanic "cvBindsAndSigs" (ppr d)
+    go []              = return (emptyBag, [], [], [], [], [])
+    go (L l (ValD b) : ds)
+      = do { (bs, ss, ts, tfis, dfis, docs) <- go ds'
+           ; return (b' `consBag` bs, ss, ts, tfis, dfis, docs) }
+      where
+        (b', ds') = getMonoBind (L l b) ds
+    go (L l decl : ds)
+      = do { (bs, ss, ts, tfis, dfis, docs) <- go ds
+           ; case decl of
+               SigD s
+                 -> return (bs, L l s : ss, ts, tfis, dfis, docs)
+               TyClD (FamDecl t)
+                 -> return (bs, ss, L l t : ts, tfis, dfis, docs)
+               InstD (TyFamInstD { tfid_inst = tfi })
+                 -> return (bs, ss, ts, L l tfi : tfis, dfis, docs)
+               InstD (DataFamInstD { dfid_inst = dfi })
+                 -> return (bs, ss, ts, tfis, L l dfi : dfis, docs)
+               DocD d
+                 -> return (bs, ss, ts, tfis, dfis, L l d : docs)
+               SpliceD d
+                 -> parseErrorSDoc l $
+                    hang (text "Declaration splices are allowed only" <+>
+                          text "at the top level:")
+                       2 (ppr d)
+               _ -> pprPanic "cvBindsAndSigs" (ppr decl) }
 
 -----------------------------------------------------------------------------
 -- Group function bindings into equation groups
diff --git a/testsuite/tests/th/all.T b/testsuite/tests/th/all.T
index 8d55bf7..bb8734e 100644
--- a/testsuite/tests/th/all.T
+++ b/testsuite/tests/th/all.T
@@ -337,4 +337,4 @@ test('T9084', normal, compile_fail, ['-v0'])
 test('T9738', normal, compile, ['-v0'])
 test('T9081', normal, compile, ['-v0'])
 test('T9066', normal, compile, ['-v0'])
-test('T9209', expect_broken(9209), compile_fail, ['-v0'])
+test('T9209', normal, compile_fail, ['-v0'])



More information about the ghc-commits mailing list