summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Klebinger <klebinger.andreas@gmx.at>2022-04-05 10:21:55 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-04-07 12:59:12 -0400
commitb3d6d23d11a19d5304538b4a55bd9b93f39a3e63 (patch)
tree4fe409dbe6d40c4b5672215b579f7d2a116371bd
parent08480d2af91b933a2cfc1e2f97a132eab6bba254 (diff)
downloadhaskell-b3d6d23d11a19d5304538b4a55bd9b93f39a3e63.tar.gz
Properly explain where INLINE pragmas can appear.
Fixes #20676
-rw-r--r--docs/users_guide/exts/pragmas.rst47
1 files changed, 41 insertions, 6 deletions
diff --git a/docs/users_guide/exts/pragmas.rst b/docs/users_guide/exts/pragmas.rst
index 5aa4e9a783..6550fd88d8 100644
--- a/docs/users_guide/exts/pragmas.rst
+++ b/docs/users_guide/exts/pragmas.rst
@@ -216,7 +216,7 @@ These pragmas control the inlining of function definitions.
.. pragma:: INLINE ⟨name⟩
- :where: top-level
+ :where: any function definition
Force GHC to inline a value.
@@ -308,9 +308,6 @@ selected, in which case the ``INLINE`` pragma is ignored. For example, for a
self-recursive function, the loop breaker can only be the function
itself, so an ``INLINE`` pragma is always ignored.
-Syntactically, an ``INLINE`` pragma for a function can be put anywhere
-its type signature could be put.
-
``INLINE`` pragmas are a particularly good idea for the
``then``/``return`` (or ``bind``/``unit``) functions in a monad. For
example, in GHC's own ``UniqueSupply`` monad code, we have: ::
@@ -321,6 +318,44 @@ example, in GHC's own ``UniqueSupply`` monad code, we have: ::
See also the ``NOINLINE`` (:ref:`noinline-pragma`) and ``INLINABLE``
(:ref:`inlinable-pragma`) pragmas.
+``INLINE`` pragma effects on various locations
+++++++++++++++++++++++++++++++++++++++++++++++
+
+Syntactically, an ``INLINE`` pragma for a function can be put anywhere
+its type signature could be put. This means a ``INLINE`` pragma can really
+be put on any definition site for a binding.
+This includes top-level, ``let`` and ``where`` bindings as well as default
+class methods and instance declarations.
+
+The pragma itself will only have an effect when the RHS of the binding it's applied
+to is used. For regular bindings this is straight forward but for class methods and
+instance definitions this can have surprising ramifications.
+
+If we consider a class definition with two instances like this: ::
+
+ class C a where
+ op1 :: a -> a
+
+ op2 :: [a] -> [a]
+ op2 xs = reverse (xs ++ xs)
+ {-# INLINE op2 #-}
+
+ instance C T1 where
+ op1 x = ...blah...
+
+ instance C T2 where
+ {-# INLINE op1 #-}
+ op1 x = ...blah...
+ op2 xs = ...blah...
+
+Then ``op2`` for the T1 instance will get an implicit ``INLINE`` pragma. This is because
+the RHS of the default method is used for ``op2`` which retains it's ``INLINE`` pragma.
+
+In the T2 instance ``op1`` gets an ``INLINE`` pragma and behaves accordingly. However ``op2`` for T2
+is **not** implemented by the default method. This means the pragma in the class definition doesn't apply
+to this instance. With no pragma being explicitly applied GHC will then decide on a proper inlining behaviour
+for ``T2``\s ``op2`` method on it's own.
+
.. _inlinable-pragma:
``INLINABLE`` pragma
@@ -328,7 +363,7 @@ See also the ``NOINLINE`` (:ref:`noinline-pragma`) and ``INLINABLE``
.. pragma:: INLINABLE ⟨name⟩
- :where: top-level
+ :where: any function definition
Suggest that the compiler always consider inlining ``name``.
@@ -375,7 +410,7 @@ The alternative spelling ``INLINEABLE`` is also accepted by GHC.
.. pragma:: NOINLINE ⟨name⟩
- :where: top-level
+ :where: any function definition
Instructs the compiler not to inline a value.