[Git][ghc/ghc][wip/T22492] Document TH splices' interaction with INCOHERENT instances
Ryan Scott (@RyanGlScott)
gitlab at gitlab.haskell.org
Thu Dec 8 23:33:32 UTC 2022
Ryan Scott pushed to branch wip/T22492 at Glasgow Haskell Compiler / GHC
Commits:
2e3de14f by Ryan Scott at 2022-12-08T18:33:01-05:00
Document TH splices' interaction with INCOHERENT instances
Top-level declaration splices can having surprising interactions with
`INCOHERENT` instances, as observed in #22492. This patch
resolves #22492 by documenting this strange interaction in the GHC User's
Guide.
[ci skip]
- - - - -
1 changed file:
- docs/users_guide/exts/template_haskell.rst
Changes:
=====================================
docs/users_guide/exts/template_haskell.rst
=====================================
@@ -285,6 +285,14 @@ The :extension:`TemplateHaskellQuotes` extension is considered safe under
includes all top-level definitions down to but not including the first
top-level declaration splice.
+ Each group is compiled just like a separately compiled module. That is:
+
+ - Later groups can "see" declarations, and instance declarations, from
+ earlier groups;
+
+ - But earlier groups cannot "see" declarations, or instance declarations,
+ from later groups.
+
Each declaration group is mutually recursive only within the group.
Declaration groups can refer to definitions within previous groups,
but not later ones.
@@ -375,6 +383,70 @@ The :extension:`TemplateHaskellQuotes` extension is considered safe under
3. Since the declaration group containing ``D`` is in the previous
declaration group, the splice ``$(th2 ...)`` *can* refer to ``D``.
+ Note that in some cases, the presence or absence of top-level declaration
+ splices can affect the *runtime* behavior of the surrounding code, because
+ the resolution of instances may differ depending on their visiblity. One
+ case where this arises is with
+ :ref:`incoherent instances <instance-overlap>` ::
+
+ module Main where
+
+ main :: IO ()
+ main = do
+ let i :: Int
+ i = 42
+ putStrLn (m1 i)
+ putStrLn (m2 i)
+
+ class C1 a where
+ m1 :: a -> String
+
+ instance {-# INCOHERENT #-} C1 a where
+ m1 _ = "C1 incoherent"
+
+ instance C1 Int where
+ m1 = show
+
+ class C2 a where
+ m2 :: a -> String
+
+ instance {-# INCOHERENT #-} C2 a where
+ m2 _ = "C2 incoherent"
+
+ $(return [])
+
+ instance C2 Int where
+ m2 = show
+
+ Here, ``C1`` and ``C2`` are the same classes with nearly identical
+ instances. The only significant differences between ``C1`` and ``C2``, aside
+ from the minor name change, is that all of ``C1``'s instances are defined
+ within the same declaration group, whereas the ``C2 Int`` instance is put in
+ a separate declaration group from the incoherent ``C2 a`` instance. This has
+ an impact on the runtime behavior of the ``main`` function ::
+
+ $ runghc Main.hs
+ 42
+ C2 incoherent
+
+ Note that ``m1 i`` returns ``"42"``, but ``m2 i`` returns
+ ``"C2 incoherent"``. When each of these expressions are typechecked, GHC
+ must figure out which ``C1 Int`` and ``C2 Int`` instances to use:
+
+ 1. When resolving the ``C1 Int`` instance, GHC discovers two possible
+ instances in the same declaration group: the incoherent ``C1 a`` instance
+ and the non-incoherent ``C1 Int`` instance. According to the instance
+ search rules described in :ref:`instance-overlap`, because there is
+ exactly one non-incoherent instance to pick, GHC will choose the
+ ``C1 Int`` instance. As a result, ``m1 i`` will be equivalent to
+ ``show i`` (i.e., ``"42"``).
+ 2. When resolving the ``C2 Int`` instance, GHC only discovers one instance
+ in the same declaration group: the incoherent ``C2 a`` instance. Note
+ that GHC does *not* see the ``C2 Int`` instance, as that is in a later
+ declaration group that is made separate by the intervening declaration
+ splice. As a result, GHC will choose the ``C2 a`` instance, making
+ ``m2 i`` equivalent to ``"C2 incoherent"``.
+
- Expression quotations accept most Haskell language constructs.
However, there are some GHC-specific extensions which expression
quotations currently do not support, including
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2e3de14fea00353bf361646a76a2aaa9c2e5cbc1
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2e3de14fea00353bf361646a76a2aaa9c2e5cbc1
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20221208/cebfa6e5/attachment-0001.html>
More information about the ghc-commits
mailing list