[commit: ghc] master: Fix Trac #9815 (4ba4cc7)

git at git.haskell.org git at git.haskell.org
Fri Nov 21 13:03:35 UTC 2014


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

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/4ba4cc7aaaf2bff31bc8474c8ba40e1cbe3e3875/ghc

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

commit 4ba4cc7aaaf2bff31bc8474c8ba40e1cbe3e3875
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Fri Nov 21 13:02:45 2014 +0000

    Fix Trac #9815
    
    Dot-dot record-wildcard notation is simply illegal for constructors
    without any named fields, but that was neither documented nor checked.
    This patch does so
    
    - Make the check in RnPat
    - Add test T9815
    - Fix CmmLayoutStack which was using the illegal form (!)
    - Document in user manual


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

4ba4cc7aaaf2bff31bc8474c8ba40e1cbe3e3875
 compiler/cmm/CmmLayoutStack.hs                  |  6 +++---
 compiler/rename/RnPat.lhs                       | 14 ++++++++++----
 docs/users_guide/glasgow_exts.xml               | 14 +++++++++++++-
 testsuite/tests/rename/should_fail/T9815.hs     |  6 ++++++
 testsuite/tests/rename/should_fail/T9815.stderr |  4 ++++
 testsuite/tests/rename/should_fail/all.T        |  1 +
 6 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/compiler/cmm/CmmLayoutStack.hs b/compiler/cmm/CmmLayoutStack.hs
index c9399b3..5a2891f 100644
--- a/compiler/cmm/CmmLayoutStack.hs
+++ b/compiler/cmm/CmmLayoutStack.hs
@@ -415,9 +415,9 @@ handleLastNode dflags procpoints liveness cont_info stackmaps
        return $ lastCall cont_lbl (wORD_SIZE dflags) ret_args ret_off
             -- one word of args: the return address
 
-    CmmBranch{..}     ->  handleBranches
-    CmmCondBranch{..} ->  handleBranches
-    CmmSwitch{..}     ->  handleBranches
+    CmmBranch {}     ->  handleBranches
+    CmmCondBranch {} ->  handleBranches
+    CmmSwitch {}     ->  handleBranches
 
   where
      -- Calls and ForeignCalls are handled the same way:
diff --git a/compiler/rename/RnPat.lhs b/compiler/rename/RnPat.lhs
index aa41361..9d03805 100644
--- a/compiler/rename/RnPat.lhs
+++ b/compiler/rename/RnPat.lhs
@@ -516,7 +516,7 @@ rnHsRecFields
     -> HsRecFields RdrName (Located arg)
     -> RnM ([HsRecField Name (Located arg)], FreeVars)
 
--- This supprisingly complicated pass
+-- This surprisingly complicated pass
 --   a) looks up the field name (possibly using disambiguation)
 --   b) fills in puns and dot-dot stuff
 -- When we we've finished, we've renamed the LHS, but not the RHS,
@@ -576,7 +576,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
       = return []
     rn_dotdot (Just {}) Nothing _flds   -- ".." on record update
       = do { case ctxt of
-                HsRecFieldUpd -> addErr badDotDot
+                HsRecFieldUpd -> addErr badDotDotUpd
                 _             -> return ()
            ; return [] }
     rn_dotdot (Just n) (Just con) flds -- ".." on record construction / pat match
@@ -586,6 +586,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
            ; checkErr dd_flag (needFlagDotDot ctxt)
            ; (rdr_env, lcl_env) <- getRdrEnvs
            ; con_fields <- lookupConstructorFields con
+           ; when (null con_fields) (addErr (badDotDotCon con))
            ; let present_flds = getFieldIds flds
                  parent_tc = find_tycon rdr_env con
 
@@ -655,8 +656,13 @@ needFlagDotDot :: HsRecFieldContext -> SDoc
 needFlagDotDot ctxt = vcat [ptext (sLit "Illegal `..' in record") <+> pprRFC ctxt,
                             ptext (sLit "Use RecordWildCards to permit this")]
 
-badDotDot :: SDoc
-badDotDot = ptext (sLit "You cannot use `..' in a record update")
+badDotDotCon :: Name -> SDoc
+badDotDotCon con
+  = vcat [ ptext (sLit "Illegal `..' notation for constructor") <+> quotes (ppr con)
+         , nest 2 (ptext (sLit "The constructor has no labelled fields")) ]
+
+badDotDotUpd :: SDoc
+badDotDotUpd = ptext (sLit "You cannot use `..' in a record update")
 
 emptyUpdateErr :: SDoc
 emptyUpdateErr = ptext (sLit "Empty record update")
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 30742b3..a21e677 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -2337,7 +2337,7 @@ More details:
 <itemizedlist>
 <listitem><para>
 Record wildcards in patterns can be mixed with other patterns, including puns
-(<xref linkend="record-puns"/>); for example, in a pattern <literal>C {a
+(<xref linkend="record-puns"/>); for example, in a pattern <literal>(C {a
 = 1, b, ..})</literal>.  Additionally, record wildcards can be used
 wherever record patterns occur, including in <literal>let</literal>
 bindings and at the top-level.  For example, the top-level binding
@@ -2404,6 +2404,18 @@ and omitting <literal>c</literal> since the variable <literal>c</literal>
 is not in scope (apart from the binding of the
 record selector <literal>c</literal>, of course).
 </para></listitem>
+
+<listitem><para>
+Record wildcards cannot be used (a) in a record update construct, and (b) for data
+constructors that are not declared with record fields.  For example:
+<programlisting>
+f x = x { v=True, .. }   -- Illegal (a)
+
+data T = MkT Int Bool
+g = MkT { .. }           -- Illegal (b)
+h (MkT { .. }) = True    -- Illegal (b)
+</programlisting>
+</para></listitem>
 </itemizedlist>
 </para>
 
diff --git a/testsuite/tests/rename/should_fail/T9815.hs b/testsuite/tests/rename/should_fail/T9815.hs
new file mode 100644
index 0000000..7d7ae66
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T9815.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE RecordWildCards #-}
+module T9815 where
+
+newtype N = N Int deriving (Show)
+
+foo = print N{..}
diff --git a/testsuite/tests/rename/should_fail/T9815.stderr b/testsuite/tests/rename/should_fail/T9815.stderr
new file mode 100644
index 0000000..99f16b6
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T9815.stderr
@@ -0,0 +1,4 @@
+
+T9815.hs:6:13:
+    Illegal `..' notation for constructor ‘N’
+      The constructor has no labelled fields
diff --git a/testsuite/tests/rename/should_fail/all.T b/testsuite/tests/rename/should_fail/all.T
index f2664dc..56d0f87 100644
--- a/testsuite/tests/rename/should_fail/all.T
+++ b/testsuite/tests/rename/should_fail/all.T
@@ -119,3 +119,4 @@ test('T9177', normal, compile_fail, [''])
 test('T9436', normal, compile_fail, [''])
 test('T9437', normal, compile_fail, [''])
 test('T9077', normal, compile_fail, [''])
+test('T9815', normal, compile_fail, [''])



More information about the ghc-commits mailing list