[commit: ghc] ghc-8.0: Fix Show derivation in the presence of RebindableSyntax/OverloadedStrings (d7a1f68)
git at git.haskell.org
git at git.haskell.org
Tue Oct 18 22:45:48 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : ghc-8.0
Link : http://ghc.haskell.org/trac/ghc/changeset/d7a1f682af766e6c1529932b24bada9053d5c4da/ghc
>---------------------------------------------------------------
commit d7a1f682af766e6c1529932b24bada9053d5c4da
Author: Ryan Scott <ryan.gl.scott at gmail.com>
Date: Sat Oct 15 11:11:20 2016 -0400
Fix Show derivation in the presence of RebindableSyntax/OverloadedStrings
Summary:
To fix this issue, we simply disable `RebindableSyntax` whenever we rename
the code generated from a deriving clause.
Fixes #12688.
Test Plan: make test TEST=T12688
Reviewers: simonpj, austin, bgamari
Reviewed By: simonpj, bgamari
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2591
GHC Trac Issues: #12688
(cherry picked from commit b501709ed79ba03e72518ef9dd101ce2d03db2de)
>---------------------------------------------------------------
d7a1f682af766e6c1529932b24bada9053d5c4da
compiler/typecheck/TcDeriv.hs | 41 ++++++++++++++++++++---
compiler/typecheck/TcRnMonad.hs | 6 +++-
docs/users_guide/8.0.2-notes.rst | 4 +++
docs/users_guide/glasgow_exts.rst | 27 +++++++++++++++
testsuite/tests/deriving/should_compile/T12688.hs | 15 +++++++++
testsuite/tests/deriving/should_compile/all.T | 1 +
6 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/compiler/typecheck/TcDeriv.hs b/compiler/typecheck/TcDeriv.hs
index c72772a..9a84952 100644
--- a/compiler/typecheck/TcDeriv.hs
+++ b/compiler/typecheck/TcDeriv.hs
@@ -439,11 +439,17 @@ renameDeriv is_boot inst_infos bagBinds
, emptyValBindsOut, usesOnly (plusFVs fvs)) }
| otherwise
- = discardWarnings $ -- Discard warnings about unused bindings etc
- setXOptM LangExt.EmptyCase $ -- Derived decls (for empty types) can have
- -- case x of {}
- setXOptM LangExt.ScopedTypeVariables $ -- Derived decls (for newtype-deriving) can
- setXOptM LangExt.KindSignatures $ -- used ScopedTypeVariables & KindSignatures
+ = discardWarnings $
+ -- Discard warnings about unused bindings etc
+ setXOptM LangExt.EmptyCase $
+ -- Derived decls (for empty types) can have
+ -- case x of {}
+ setXOptM LangExt.ScopedTypeVariables $
+ setXOptM LangExt.KindSignatures $
+ -- Derived decls (for newtype-deriving) can use ScopedTypeVariables &
+ -- KindSignatures
+ unsetXOptM LangExt.RebindableSyntax $
+ -- See Note [Avoid RebindableSyntax when deriving]
do {
-- Bring the extra deriving stuff into scope
-- before renaming the instances themselves
@@ -513,6 +519,31 @@ dropped patterns have.
Also, this technique carries over the kind substitution from deriveTyData
nicely.
+Note [Avoid RebindableSyntax when deriving]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The RebindableSyntax extension interacts awkwardly with the derivation of
+any stock class whose methods require the use of string literals. The Show
+class is a simple example (see Trac #12688):
+
+ {-# LANGUAGE RebindableSyntax, OverloadedStrings #-}
+ newtype Text = Text String
+ fromString :: String -> Text
+ fromString = Text
+
+ data Foo = Foo deriving Show
+
+This will generate code to the effect of:
+
+ instance Show Foo where
+ showsPrec _ Foo = showString "Foo"
+
+But because RebindableSyntax and OverloadedStrings are enabled, the "Foo"
+string literal is now of type Text, not String, which showString doesn't
+accept! This causes the generated Show instance to fail to typecheck.
+
+To avoid this kind of scenario, we simply turn off RebindableSyntax entirely
+in derived code.
+
************************************************************************
* *
From HsSyn to DerivSpec
diff --git a/compiler/typecheck/TcRnMonad.hs b/compiler/typecheck/TcRnMonad.hs
index 21035d6..278082e 100644
--- a/compiler/typecheck/TcRnMonad.hs
+++ b/compiler/typecheck/TcRnMonad.hs
@@ -18,7 +18,7 @@ module TcRnMonad(
setGblEnv, getLclEnv, updLclEnv, setLclEnv,
getEnvs, setEnvs,
xoptM, doptM, goptM, woptM,
- setXOptM, unsetGOptM, unsetWOptM,
+ setXOptM, unsetXOptM, unsetGOptM, unsetWOptM,
whenDOptM, whenGOptM, whenWOptM, whenXOptM,
getGhcMode,
withDoDynamicToo,
@@ -447,6 +447,10 @@ setXOptM :: LangExt.Extension -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
setXOptM flag =
updTopEnv (\top -> top { hsc_dflags = xopt_set (hsc_dflags top) flag})
+unsetXOptM :: LangExt.Extension -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
+unsetXOptM flag =
+ updTopEnv (\top -> top { hsc_dflags = xopt_unset (hsc_dflags top) flag})
+
unsetGOptM :: GeneralFlag -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
unsetGOptM flag =
updTopEnv (\top -> top { hsc_dflags = gopt_unset (hsc_dflags top) flag})
diff --git a/docs/users_guide/8.0.2-notes.rst b/docs/users_guide/8.0.2-notes.rst
index 668474a..b1568ae 100644
--- a/docs/users_guide/8.0.2-notes.rst
+++ b/docs/users_guide/8.0.2-notes.rst
@@ -21,6 +21,10 @@ Language
- TODO FIXME.
+- A bug has been fixed that caused derived ``Show`` instances to fail in the
+ presence of :ghc-flag:`-XRebindableSyntax` and
+ :ghc-flag:`-XOverloadedStrings` (:ghc-ticket:`12688`).
+
Compiler
~~~~~~~~
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index d7ba481..5153d07 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -1464,6 +1464,33 @@ Be warned: this is an experimental facility, with fewer checks than
usual. Use ``-dcore-lint`` to typecheck the desugared program. If Core
Lint is happy you should be all right.
+Things unaffected by :ghc-flag:`-XRebindableSyntax`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:ghc-flag:`-XRebindableSyntax` does not apply to any code generated from a
+``deriving`` clause or declaration. To see why, consider the following code: ::
+
+ {-# LANGUAGE RebindableSyntax, OverloadedStrings #-}
+ newtype Text = Text String
+
+ fromString :: String -> Text
+ fromString = Text
+
+ data Foo = Foo deriving Show
+
+This will generate code to the effect of: ::
+
+ instance Show Foo where
+ showsPrec _ Foo = showString "Foo"
+
+But because :ghc-flag:`-XRebindableSyntax` and :ghc-flag:`-XOverloadedStrings`
+are enabled, the ``"Foo"`` string literal would now be of type ``Text``, not
+``String``, which ``showString`` doesn't accept! This causes the generated
+``Show`` instance to fail to typecheck. It's hard to imagine any scenario where
+it would be desirable have :ghc-flag:`-XRebindableSyntax` behavior within
+derived code, so GHC simply ignores :ghc-flag:`-XRebindableSyntax` entirely
+when checking derived code.
+
.. _postfix-operators:
Postfix operators
diff --git a/testsuite/tests/deriving/should_compile/T12688.hs b/testsuite/tests/deriving/should_compile/T12688.hs
new file mode 100644
index 0000000..0735a81
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T12688.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE RebindableSyntax, OverloadedStrings #-}
+module T12688 where
+
+import Prelude (String,Show(..))
+
+newtype Text = Text String
+
+fromString :: String -> Text
+fromString = Text
+
+x :: Text
+x = "x"
+
+newtype Foo = Foo ()
+ deriving (Show)
diff --git a/testsuite/tests/deriving/should_compile/all.T b/testsuite/tests/deriving/should_compile/all.T
index d79aa6d..1261aaa 100644
--- a/testsuite/tests/deriving/should_compile/all.T
+++ b/testsuite/tests/deriving/should_compile/all.T
@@ -74,3 +74,4 @@ test('T11837', normal, compile, [''])
test('T12399', normal, compile, [''])
test('T12583', normal, compile, [''])
test('T12616', normal, compile, [''])
+test('T12688', normal, compile, [''])
More information about the ghc-commits
mailing list