summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kraeutmann <kane@kane.cx>2015-12-07 11:19:28 +0100
committerBen Gamari <ben@smart-cactus.org>2015-12-07 11:20:57 +0100
commit8cef8af3286f3c98f2a02e65371b875d8791b687 (patch)
tree98dbb8851c8496d1266d7a91625026ecd314de53
parent3d55e41e72dc32281744c52afea380c1db577ee1 (diff)
downloadhaskell-8cef8af3286f3c98f2a02e65371b875d8791b687.tar.gz
Re-export data family when exporting a data instance without an export list
Whenever a data instance is exported, the corresponding data family is exported, too. This allows one to write ``` -- Foo.hs module Foo where data family T a -- Bar.hs module Bar where import Foo data instance T Int = MkT -- Baz.hs module Baz where import Bar (T(MkT)) ``` In previous versions of GHC, this required a workaround explicit export list in `Bar`. Reviewers: bgamari, goldfire, austin Reviewed By: bgamari, goldfire Subscribers: goldfire, thomie Differential Revision: https://phabricator.haskell.org/D1573 GHC Trac Issues: #11164
-rw-r--r--compiler/rename/RnNames.hs26
-rw-r--r--docs/users_guide/7.12.1-notes.rst23
-rw-r--r--docs/users_guide/glasgow_exts.rst8
-rw-r--r--testsuite/tests/ghci/scripts/T5417.stdout2
-rw-r--r--testsuite/tests/indexed-types/should_fail/Over.stderr20
-rw-r--r--testsuite/tests/rename/should_compile/T11164.hs3
-rw-r--r--testsuite/tests/rename/should_compile/T11164a.hs4
-rw-r--r--testsuite/tests/rename/should_compile/T11164b.hs6
-rw-r--r--testsuite/tests/rename/should_compile/all.T4
9 files changed, 74 insertions, 22 deletions
diff --git a/compiler/rename/RnNames.hs b/compiler/rename/RnNames.hs
index b0b79f55e6..3ee1e695a4 100644
--- a/compiler/rename/RnNames.hs
+++ b/compiler/rename/RnNames.hs
@@ -1200,14 +1200,24 @@ exports_from_avail :: Maybe (Located [LIE RdrName])
-> RnM (Maybe [LIE Name], [AvailInfo])
exports_from_avail Nothing rdr_env _imports _this_mod
- = -- The same as (module M) where M is the current module name,
- -- so that's how we handle it.
- let
- avails = [ availFromGRE gre
- | gre <- globalRdrEnvElts rdr_env
- , isLocalGRE gre ]
- in
- return (Nothing, avails)
+ -- The same as (module M) where M is the current module name,
+ -- so that's how we handle it, except we also export the data family
+ -- when a data instance is exported.
+ = let avails = [ fix_faminst $ availFromGRE gre
+ | gre <- globalRdrEnvElts rdr_env
+ , isLocalGRE gre ]
+ in return (Nothing, avails)
+ where
+ -- #11164: when we define a data instance
+ -- but not data family, re-export the family
+ -- Generally, whenever we export a part of a declaration,
+ -- export the declaration, too.
+ fix_faminst (AvailTC n ns flds)
+ | not (n `elem` ns)
+ = AvailTC n (n:ns) flds
+
+ fix_faminst avail = avail
+
exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
= do (ie_names, _, exports) <- foldlM do_litem emptyExportAccum rdr_items
diff --git a/docs/users_guide/7.12.1-notes.rst b/docs/users_guide/7.12.1-notes.rst
index 2e0ae6f18c..21ec1d39b3 100644
--- a/docs/users_guide/7.12.1-notes.rst
+++ b/docs/users_guide/7.12.1-notes.rst
@@ -109,6 +109,29 @@ Language
-- P is imported
import Foo (T(..))
+- Whenever a data instance is exported, the corresponding data family
+ is exported, too. This allows one to write ::
+
+ -- Foo.hs
+ module Foo where
+
+ data family T a
+
+ -- Bar.hs
+ module Bar where
+
+ import Foo
+
+ data instance T Int = MkT
+
+ -- Baz.hs
+ module Baz where
+
+ import Bar (T(MkT))
+
+ In previous versions of GHC, this required a workaround via an
+ explicit export list in Bar.
+
Compiler
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index 93261a2227..7e448beb9c 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -6702,10 +6702,10 @@ Two things to watch out for:
data instance D Int = D1 | D2
Module Y exports all the entities defined in Y, namely the data
- constructors ``D1`` and ``D2``, *but not the data family* ``D``. That
- (annoyingly) means that you cannot selectively import Y selectively,
- thus "``import Y( D(D1,D2) )``", because Y does not export ``D``.
- Instead you should list the exports explicitly, thus:
+ constructors ``D1`` and ``D2``, and *implicitly* the data family ``D``,
+ even though it's defined in X.
+ This means you can write "``import Y( D(D1,D2) )``" *without*
+ giving an explicit export list like this:
::
diff --git a/testsuite/tests/ghci/scripts/T5417.stdout b/testsuite/tests/ghci/scripts/T5417.stdout
index 06329d9a1d..30178a44ab 100644
--- a/testsuite/tests/ghci/scripts/T5417.stdout
+++ b/testsuite/tests/ghci/scripts/T5417.stdout
@@ -3,5 +3,7 @@ data instance C.F (B1 a) = B2 a
data family D a
class C.C1 a where
data family C.F a
+class C.C1 a where
+ data family C.F a
-- Defined at T5417a.hs:5:5
data instance C.F (B1 a) = B2 a -- Defined at T5417.hs:8:10
diff --git a/testsuite/tests/indexed-types/should_fail/Over.stderr b/testsuite/tests/indexed-types/should_fail/Over.stderr
index 180bb954ef..63b8b304b2 100644
--- a/testsuite/tests/indexed-types/should_fail/Over.stderr
+++ b/testsuite/tests/indexed-types/should_fail/Over.stderr
@@ -1,10 +1,10 @@
-
-OverB.hs:7:15:
- Conflicting family instance declarations:
- OverA.C [Int] [a] = CListList2 -- Defined at OverB.hs:7:15
- OverA.C [a] [Int] = C9ListList -- Defined at OverC.hs:7:15
-
-OverB.hs:9:15:
- Conflicting family instance declarations:
- OverA.D [Int] [a] = Int -- Defined at OverB.hs:9:15
- OverA.D [a] [Int] = Char -- Defined at OverC.hs:9:15
+
+OverB.hs:7:15: error:
+ Conflicting family instance declarations:
+ C [Int] [a] = CListList2 -- Defined at OverB.hs:7:15
+ C [a] [Int] = C9ListList -- Defined at OverC.hs:7:15
+
+OverB.hs:9:15: error:
+ Conflicting family instance declarations:
+ OverA.D [Int] [a] = Int -- Defined at OverB.hs:9:15
+ OverA.D [a] [Int] = Char -- Defined at OverC.hs:9:15
diff --git a/testsuite/tests/rename/should_compile/T11164.hs b/testsuite/tests/rename/should_compile/T11164.hs
new file mode 100644
index 0000000000..b1d9a68a6c
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/T11164.hs
@@ -0,0 +1,3 @@
+module T11164 where
+
+import T11164b (T)
diff --git a/testsuite/tests/rename/should_compile/T11164a.hs b/testsuite/tests/rename/should_compile/T11164a.hs
new file mode 100644
index 0000000000..f14e96d211
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/T11164a.hs
@@ -0,0 +1,4 @@
+{-# LANGUAGE TypeFamilies #-}
+module T11164a where
+
+data family T a
diff --git a/testsuite/tests/rename/should_compile/T11164b.hs b/testsuite/tests/rename/should_compile/T11164b.hs
new file mode 100644
index 0000000000..abe65c4788
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/T11164b.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE TypeFamilies #-}
+module T11164b where
+
+import T11164a
+
+data instance T Int = MkT
diff --git a/testsuite/tests/rename/should_compile/all.T b/testsuite/tests/rename/should_compile/all.T
index c501eccd56..05bc2507d0 100644
--- a/testsuite/tests/rename/should_compile/all.T
+++ b/testsuite/tests/rename/should_compile/all.T
@@ -226,3 +226,7 @@ test('T7969',
test('T9127', normal, compile, [''])
test('T4426', normal, compile_fail, [''])
test('T9778', normal, compile, ['-fwarn-unticked-promoted-constructors'])
+test('T11164',
+ extra_clean(['T11164a.hi', 'T11164a.o',
+ 'T11164b.hi', 'T11164b.o']),
+ multimod_compile, ['T11164', '-v0'])