-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Examine values for unexpected thunks
--   
--   Long lived application data typically should not contain any thunks.
--   This library can be used to examine values for unexpected thunks,
--   which can then be used in assertions. This can be invaluable in
--   avoiding memory leaks, or tracking down existing ones.
@package nothunks
@version 0.3.1

module NoThunks.Class

-- | Check a value for unexpected thunks
class NoThunks a

-- | Check if the argument does not contain any unexpected thunks
--   
--   For most datatypes, we should have that
--   
--   <pre>
--   noThunks ctxt x == Nothing
--   </pre>
--   
--   if and only if
--   
--   <pre>
--   checkContainsThunks x
--   </pre>
--   
--   For some datatypes however, some thunks are expected. For example, the
--   internal fingertree <a>Sequence</a> might contain thunks (this is
--   important for the asymptotic complexity of this data structure).
--   However, we should still check that the <i>values</i> in the sequence
--   don't contain any unexpected thunks.
--   
--   This means that we need to traverse the sequence, which might force
--   some of the thunks in the tree. In general, it is acceptable for
--   <a>noThunks</a> to force such "expected thunks", as long as it always
--   reports the <i>unexpected</i> thunks.
--   
--   The default implementation of <a>noThunks</a> checks that the argument
--   is in WHNF, and if so, adds the type into the context (using
--   <a>showTypeOf</a> or <a>whereFrom</a> if available), and calls
--   <a>wNoThunks</a>. See <a>ThunkInfo</a> for a detailed discussion of
--   the type context.
--   
--   See also discussion of caveats listed for <a>checkContainsThunks</a>.
noThunks :: NoThunks a => Context -> a -> IO (Maybe ThunkInfo)

-- | Check that the argument is in normal form, assuming it is in WHNF.
--   
--   The context will already have been extended with the type we're
--   looking at, so all that's left is to look at the thunks <i>inside</i>
--   the type. The default implementation uses GHC Generics to do this.
wNoThunks :: NoThunks a => Context -> a -> IO (Maybe ThunkInfo)
($dmwNoThunks) :: (NoThunks a, Generic a, GWNoThunks ('[] :: [Symbol]) (Rep a)) => Context -> a -> IO (Maybe ThunkInfo)

-- | Show type <tt>a</tt> (to add to the context)
--   
--   We try hard to avoid <a>Typeable</a> constraints in this module: there
--   are types with no <a>Typeable</a> instance but with a <a>NoThunks</a>
--   instance (most important example are types such as <tt>ST s</tt> which
--   rely on parametric polymorphism). By default we should therefore only
--   show the "outer layer"; for example, if we have a type
--   
--   <pre>
--   Seq (ST s ())
--   </pre>
--   
--   then <a>showTypeOf</a> should just give <tt>Seq</tt>, leaving it up to
--   the instance for <tt>ST</tt> to decide how to implement
--   <a>showTypeOf</a>; this keeps things compositional. The default
--   implementation does precisely this using the metadata that GHC
--   Generics provides.
--   
--   For convenience, however, some of the <tt>deriving via</tt> newtype
--   wrappers we provide <i>do</i> depend on <tt>Typeable</tt>; see below.
showTypeOf :: NoThunks a => Proxy a -> String
($dmshowTypeOf) :: (NoThunks a, Generic a, GShowTypeOf (Rep a)) => Proxy a -> String

-- | Information about unexpected thunks
--   
--   ThunkInfo contains either precise <a>Info</a> about the thunk location
--   or <a>Context</a> to make it easier to debug space leaks. <a>Info</a>
--   is available if
--   
--   <ul>
--   <li><tt>GHC-9.4</tt> or newer is used,</li>
--   <li>the code is compiled with <tt>-finfo-table-map</tt> and is
--   improved if <tt>-fdistinct-constructor-tables</tt> is used as
--   well.</li>
--   </ul>
--   
--   The <tt>Context</tt> argument is intended to give a clue to add
--   debugging. For example, suppose we have something of type <tt>(Int,
--   [Int])</tt>. The various contexts we might get are
--   
--   <pre>
--   Context                  The thunk is..
--   ---------------------------------------------------------------------
--   ["(,)"]                  the pair itself
--   ["Int","(,)"]            the Int in the pair
--   ["List","(,)"]           the [Int] in the pair
--   ["Int","List","(,)"]     an Int in the [Int] in the pair
--   </pre>
--   
--   Note: prior to `ghc-9.6` a list was indicated by `[]`.
data ThunkInfo
ThunkInfo :: Context -> Maybe Info -> ThunkInfo
[thunkContext] :: ThunkInfo -> Context
[thunkInfo] :: ThunkInfo -> Maybe Info

-- | Construct <a>ThunkInfo</a> either from <a>Context</a> or information
--   provided by <tt>GHC</tt> about <tt>a</tt> (see <a>whereFrom</a>).
mkThunkInfo :: Context -> a -> IO ThunkInfo

-- | Context where a thunk was found
--   
--   This is intended to give a hint about which thunk was found. For
--   example, a thunk might be reported with context
--   
--   <pre>
--   ["Int", "(,)", "Map", "AppState"]
--   </pre>
--   
--   telling you that you have an <tt>AppState</tt> containing a
--   <tt>Map</tt> containing a pair, all of which weren't thunks (were in
--   WHNF), but that pair contained an <tt>Int</tt> which was a thunk.
type Context = [String]

-- | Binding name, type and location information about the thunk, e.g.
--   
--   <pre>
--   fromModel :: Int @ test/Test/NoThunks/Class.hs:198:53-84
--   </pre>
type Info = String

-- | Call <a>noThunks</a> in a pure context (relies on
--   <a>unsafePerformIO</a>).
unsafeNoThunks :: NoThunks a => a -> Maybe ThunkInfo

-- | Short-circuit a list of checks
allNoThunks :: [IO (Maybe ThunkInfo)] -> IO (Maybe ThunkInfo)

-- | Check that all elements in the list are thunk-free
--   
--   Does not check the list itself. Useful for checking the elements of a
--   container.
--   
--   See also <a>noThunksInKeysAndValues</a>
noThunksInValues :: NoThunks a => Context -> [a] -> IO (Maybe ThunkInfo)

-- | Variant on <a>noThunksInValues</a> for keyed containers.
--   
--   Neither the list nor the tuples are checked for thunks.
noThunksInKeysAndValues :: (NoThunks k, NoThunks v) => Context -> [(k, v)] -> IO (Maybe ThunkInfo)

-- | Newtype wrapper for use with <tt>deriving via</tt> to check for WHNF
--   only
--   
--   For some types we don't want to check for nested thunks, and we only
--   want check if the argument is in WHNF, not in NF. A typical example
--   are functions; see the instance of <tt>(a -&gt; b)</tt> for detailed
--   discussion. This should be used sparingly.
--   
--   Example:
--   
--   <pre>
--   deriving via OnlyCheckWhnf T instance NoThunks T
--   </pre>
newtype OnlyCheckWhnf a
OnlyCheckWhnf :: a -> OnlyCheckWhnf a

-- | Variant on <a>OnlyCheckWhnf</a> that does not depend on <a>Generic</a>
--   
--   Example:
--   
--   <pre>
--   deriving via OnlyCheckWhnfNamed "T" T instance NoThunks T
--   </pre>
newtype OnlyCheckWhnfNamed (name :: Symbol) a
OnlyCheckWhnfNamed :: a -> OnlyCheckWhnfNamed (name :: Symbol) a

-- | Newtype wrapper for use with <tt>deriving via</tt> to inspect the heap
--   directly
--   
--   This bypasses the class instances altogether, and inspects the GHC
--   heap directly, checking that the value does not contain any thunks
--   <i>anywhere</i>. Since we can do this without any type classes
--   instances, this is useful for types that contain fields for which
--   <a>NoThunks</a> instances are not available.
--   
--   Since the primary use case for <a>InspectHeap</a> then is to give
--   instances for <a>NoThunks</a> from third party libraries, we also
--   don't want to rely on a <a>Generic</a> instance, which may likewise
--   not be available. Instead, we will rely on <a>Typeable</a>, which is
--   available for <i>all</i> types. However, as <a>showTypeOf</a>
--   explains, requiring <a>Typeable</a> may not always be suitable; if it
--   isn't, <a>InspectHeapNamed</a> can be used.
--   
--   Example:
--   
--   <pre>
--   deriving via InspectHeap T instance NoThunks T
--   </pre>
newtype InspectHeap a
InspectHeap :: a -> InspectHeap a

-- | Variant on <a>InspectHeap</a> that does not depend on <a>Typeable</a>.
--   
--   <pre>
--   deriving via InspectHeapNamed "T" T instance NoUnexpecedThunks T
--   </pre>
newtype InspectHeapNamed (name :: Symbol) a
InspectHeapNamed :: a -> InspectHeapNamed (name :: Symbol) a

-- | Newtype wrapper for values that should be allowed to be a thunk
--   
--   This should be used <i>VERY</i> sparingly, and should <i>ONLY</i> be
--   used on values (or, even rarer, types) which you are <i>SURE</i>
--   cannot retain any data that they shouldn't. Bear in mind allowing a
--   value of type <tt>T</tt> to be a thunk might cause a value of type
--   <tt>S</tt> to be retained if <tt>T</tt> was computed from <tt>S</tt>.
newtype AllowThunk a
AllowThunk :: a -> AllowThunk a

-- | Newtype wrapper for records where some of the fields are allowed to be
--   thunks.
--   
--   Example:
--   
--   <pre>
--   deriving via AllowThunksIn '["foo","bar"] T instance NoThunks T
--   </pre>
--   
--   This will create an instance that skips the thunk checks for the "foo"
--   and "bar" fields.
newtype AllowThunksIn (fields :: [Symbol]) a
AllowThunksIn :: a -> AllowThunksIn (fields :: [Symbol]) a

-- | Generic infrastructure for checking for unexpected thunks
--   
--   The <tt>a</tt> argument records which record fields are allowed to
--   contain thunks; see <a>AllowThunksIn</a> and <a>GWRecordField</a>,
--   below.
class GWNoThunks (a :: [Symbol]) (f :: Type -> Type)

-- | Check that the argument does not contain any unexpected thunks
--   
--   Precondition: the argument is in WHNF.
gwNoThunks :: GWNoThunks a f => proxy a -> Context -> f x -> IO (Maybe ThunkInfo)
instance GHC.Internal.Generics.Datatype c => NoThunks.Class.GShowTypeOf (GHC.Internal.Generics.D1 c f)
instance (NoThunks.Class.GWNoThunks a f, NoThunks.Class.GWNoThunks a g) => NoThunks.Class.GWNoThunks a (f GHC.Internal.Generics.:*: g)
instance (NoThunks.Class.GWNoThunks a f, NoThunks.Class.GWNoThunks a g) => NoThunks.Class.GWNoThunks a (f GHC.Internal.Generics.:+: g)
instance NoThunks.Class.NoThunks c => NoThunks.Class.GWNoThunks a (GHC.Internal.Generics.K1 i c)
instance (NoThunks.Class.GWRecordField f (NoThunks.Class.Elem fieldName a), GHC.Internal.TypeLits.KnownSymbol fieldName) => NoThunks.Class.GWNoThunks a (GHC.Internal.Generics.S1 ('GHC.Internal.Generics.MetaSel ('GHC.Internal.Maybe.Just fieldName) su ss ds) f)
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Internal.Generics.D1 c f)
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Internal.Generics.C1 c f)
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Internal.Generics.S1 ('GHC.Internal.Generics.MetaSel 'GHC.Internal.Maybe.Nothing su ss ds) f)
instance NoThunks.Class.GWNoThunks a GHC.Internal.Generics.U1
instance NoThunks.Class.GWNoThunks a GHC.Internal.Generics.V1
instance NoThunks.Class.GWNoThunks '[] f => NoThunks.Class.GWRecordField f 'GHC.Types.False
instance NoThunks.Class.GWRecordField f 'GHC.Types.True
instance (GHC.Internal.Records.HasField x a t, NoThunks.Class.HasFields xs a) => NoThunks.Class.HasFields (x : xs) a
instance NoThunks.Class.HasFields '[] a
instance NoThunks.Class.NoThunks GHC.Internal.Data.Semigroup.Internal.All
instance NoThunks.Class.NoThunks (NoThunks.Class.AllowThunk a)
instance (NoThunks.Class.HasFields s a, GHC.Internal.Generics.Generic a, GHC.Internal.Data.Typeable.Internal.Typeable a, NoThunks.Class.GWNoThunks s (GHC.Internal.Generics.Rep a)) => NoThunks.Class.NoThunks (NoThunks.Class.AllowThunksIn s a)
instance NoThunks.Class.NoThunks (f a) => NoThunks.Class.NoThunks (GHC.Internal.Data.Semigroup.Internal.Alt f a)
instance NoThunks.Class.NoThunks GHC.Internal.Data.Semigroup.Internal.Any
instance NoThunks.Class.NoThunks (f a) => NoThunks.Class.NoThunks (GHC.Internal.Data.Monoid.Ap f a)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b) => NoThunks.Class.NoThunks (Data.Semigroup.Arg a b)
instance NoThunks.Class.NoThunks GHC.Types.Bool
instance NoThunks.Class.NoThunks Data.ByteString.Lazy.Internal.ByteString
instance NoThunks.Class.NoThunks Data.ByteString.Internal.Type.ByteString
instance NoThunks.Class.NoThunks GHC.Internal.Stack.Types.CallStack
instance NoThunks.Class.NoThunks GHC.Types.Char
instance NoThunks.Class.NoThunks Data.Time.Calendar.Days.Day
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.DiffTime.DiffTime
instance NoThunks.Class.NoThunks GHC.Types.Double
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Semigroup.Internal.Dual a)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b) => NoThunks.Class.NoThunks (GHC.Internal.Data.Either.Either a b)
instance NoThunks.Class.NoThunks (a -> b)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Monoid.First a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Semigroup.First a)
instance NoThunks.Class.NoThunks GHC.Types.Float
instance NoThunks.Class.NoThunks (GHC.Types.IO a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.IORef.IORef a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Functor.Identity.Identity a)
instance GHC.Internal.Data.Typeable.Internal.Typeable a => NoThunks.Class.NoThunks (NoThunks.Class.InspectHeap a)
instance GHC.Internal.TypeLits.KnownSymbol name => NoThunks.Class.NoThunks (NoThunks.Class.InspectHeapNamed name a)
instance NoThunks.Class.NoThunks GHC.Types.Int
instance NoThunks.Class.NoThunks GHC.Internal.Int.Int16
instance NoThunks.Class.NoThunks GHC.Internal.Int.Int32
instance NoThunks.Class.NoThunks GHC.Internal.Int.Int64
instance NoThunks.Class.NoThunks GHC.Internal.Int.Int8
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.IntMap.Internal.IntMap a)
instance NoThunks.Class.NoThunks GHC.Num.Integer.Integer
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Monoid.Last a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Semigroup.Last a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks [a]
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.LocalTime.LocalTime
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.MVar.MVar a)
instance (NoThunks.Class.NoThunks k, NoThunks.Class.NoThunks v) => NoThunks.Class.NoThunks (Data.Map.Internal.Map k v)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Semigroup.Max a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Maybe.Maybe a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Semigroup.Min a)
instance NoThunks.Class.NoThunks GHC.Num.Natural.Natural
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Base.NonEmpty a)
instance GHC.Internal.Data.Typeable.Internal.Typeable a => NoThunks.Class.NoThunks (NoThunks.Class.OnlyCheckWhnf a)
instance GHC.Internal.TypeLits.KnownSymbol name => NoThunks.Class.NoThunks (NoThunks.Class.OnlyCheckWhnfNamed name a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Semigroup.Internal.Product a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Real.Ratio a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Sequence.Internal.Seq a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Set.Internal.Set a)
instance NoThunks.Class.NoThunks Data.ByteString.Short.Internal.ShortByteString
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Tuple.Solo a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Data.Semigroup.Internal.Sum a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Internal.Conc.Sync.TVar a)
instance NoThunks.Class.NoThunks Data.Text.Internal.Lazy.Text
instance NoThunks.Class.NoThunks Data.Text.Internal.Text
instance NoThunks.Class.NoThunks GHC.Internal.Conc.Sync.ThreadId
instance NoThunks.Class.NoThunks Data.Time.Format.Locale.TimeLocale
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.TimeZone.TimeZone
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b) => NoThunks.Class.NoThunks (a, b)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b, NoThunks.Class.NoThunks c) => NoThunks.Class.NoThunks (a, b, c)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b, NoThunks.Class.NoThunks c, NoThunks.Class.NoThunks d) => NoThunks.Class.NoThunks (a, b, c, d)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b, NoThunks.Class.NoThunks c, NoThunks.Class.NoThunks d, NoThunks.Class.NoThunks e) => NoThunks.Class.NoThunks (a, b, c, d, e)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b, NoThunks.Class.NoThunks c, NoThunks.Class.NoThunks d, NoThunks.Class.NoThunks e, NoThunks.Class.NoThunks f) => NoThunks.Class.NoThunks (a, b, c, d, e, f)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b, NoThunks.Class.NoThunks c, NoThunks.Class.NoThunks d, NoThunks.Class.NoThunks e, NoThunks.Class.NoThunks f, NoThunks.Class.NoThunks g) => NoThunks.Class.NoThunks (a, b, c, d, e, f, g)
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.UTCTime.UTCTime
instance NoThunks.Class.NoThunks ()
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.UniversalTime.UniversalTime
instance NoThunks.Class.NoThunks (Data.Vector.Unboxed.Base.Vector a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Vector.Vector a)
instance NoThunks.Class.NoThunks GHC.Internal.Base.Void
instance NoThunks.Class.NoThunks GHC.Types.Word
instance NoThunks.Class.NoThunks GHC.Internal.Word.Word16
instance NoThunks.Class.NoThunks GHC.Internal.Word.Word32
instance NoThunks.Class.NoThunks GHC.Internal.Word.Word64
instance NoThunks.Class.NoThunks GHC.Internal.Word.Word8
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Semigroup.WrappedMonoid a)
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
instance GHC.Internal.Show.Show NoThunks.Class.ThunkInfo
