-- 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.1.5

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>), 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)

-- | 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, Generic a, GWNoThunks '[] (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

-- | 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, Generic a, GShowTypeOf (Rep a)) => Proxy a -> String

-- | Information about unexpected thunks
--   
--   TODO: The ghc-debug work by Matthew Pickering includes some work that
--   allows to get source spans from closures. If we could take advantage
--   of that, we could not only show the type of the unexpected thunk, but
--   also where it got allocated.
newtype ThunkInfo
ThunkInfo :: Context -> ThunkInfo
[thunkContext] :: ThunkInfo -> Context

-- | 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]

-- | 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

-- | 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.Show.Show NoThunks.Class.ThunkInfo
instance NoThunks.Class.NoThunks GHC.Types.Bool
instance NoThunks.Class.NoThunks GHC.Num.Natural.Natural
instance NoThunks.Class.NoThunks GHC.Num.Integer.Integer
instance NoThunks.Class.NoThunks GHC.Types.Float
instance NoThunks.Class.NoThunks GHC.Types.Double
instance NoThunks.Class.NoThunks GHC.Types.Char
instance NoThunks.Class.NoThunks GHC.Types.Int
instance NoThunks.Class.NoThunks GHC.Int.Int8
instance NoThunks.Class.NoThunks GHC.Int.Int16
instance NoThunks.Class.NoThunks GHC.Int.Int32
instance NoThunks.Class.NoThunks GHC.Int.Int64
instance NoThunks.Class.NoThunks GHC.Types.Word
instance NoThunks.Class.NoThunks GHC.Word.Word8
instance NoThunks.Class.NoThunks GHC.Word.Word16
instance NoThunks.Class.NoThunks GHC.Word.Word32
instance NoThunks.Class.NoThunks GHC.Word.Word64
instance NoThunks.Class.NoThunks Data.Time.Calendar.Days.Day
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.DiffTime.DiffTime
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.LocalTime.LocalTime
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime
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 Data.Time.Clock.Internal.UniversalTime.UniversalTime
instance NoThunks.Class.NoThunks Data.Time.Clock.Internal.UTCTime.UTCTime
instance NoThunks.Class.NoThunks Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
instance NoThunks.Class.NoThunks Data.ByteString.Internal.Type.ByteString
instance NoThunks.Class.NoThunks Data.ByteString.Short.Internal.ShortByteString
instance NoThunks.Class.NoThunks Data.Text.Internal.Text
instance NoThunks.Class.NoThunks GHC.Conc.Sync.ThreadId
instance NoThunks.Class.NoThunks (a -> b)
instance NoThunks.Class.NoThunks (GHC.Types.IO a)
instance NoThunks.Class.NoThunks GHC.Stack.Types.CallStack
instance (NoThunks.Class.HasFields s a, GHC.Generics.Generic a, Data.Typeable.Internal.Typeable a, NoThunks.Class.GWNoThunks s (GHC.Generics.Rep a)) => NoThunks.Class.NoThunks (NoThunks.Class.AllowThunksIn s a)
instance NoThunks.Class.HasFields '[] a
instance (GHC.Records.HasField x a t, NoThunks.Class.HasFields xs a) => NoThunks.Class.HasFields (x : xs) a
instance (NoThunks.Class.GWRecordField f (NoThunks.Class.Elem fieldName a), GHC.TypeLits.KnownSymbol fieldName) => NoThunks.Class.GWNoThunks a (GHC.Generics.S1 ('GHC.Generics.MetaSel ('GHC.Maybe.Just fieldName) su ss ds) f)
instance Data.Typeable.Internal.Typeable a => NoThunks.Class.NoThunks (NoThunks.Class.OnlyCheckWhnf a)
instance GHC.TypeLits.KnownSymbol name => NoThunks.Class.NoThunks (NoThunks.Class.OnlyCheckWhnfNamed name a)
instance NoThunks.Class.NoThunks (NoThunks.Class.AllowThunk a)
instance Data.Typeable.Internal.Typeable a => NoThunks.Class.NoThunks (NoThunks.Class.InspectHeap a)
instance GHC.TypeLits.KnownSymbol name => NoThunks.Class.NoThunks (NoThunks.Class.InspectHeapNamed name a)
instance NoThunks.Class.NoThunks c => NoThunks.Class.GWNoThunks a (GHC.Generics.K1 i c)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.IORef.IORef a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.MVar.MVar a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Conc.Sync.TVar a)
instance NoThunks.Class.NoThunks Data.ByteString.Lazy.Internal.ByteString
instance NoThunks.Class.NoThunks Data.Text.Internal.Lazy.Text
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 GHC.Base.Void
instance NoThunks.Class.NoThunks ()
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks [a]
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Functor.Identity.Identity a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Maybe.Maybe a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Base.NonEmpty a)
instance (NoThunks.Class.NoThunks a, NoThunks.Class.NoThunks b) => NoThunks.Class.NoThunks (Data.Either.Either a b)
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.Set.Internal.Set a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.IntMap.Internal.IntMap a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Vector.Vector a)
instance NoThunks.Class.NoThunks (Data.Vector.Unboxed.Base.Vector a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (Data.Sequence.Internal.Seq a)
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks (GHC.Real.Ratio a)
instance GHC.Generics.Datatype c => NoThunks.Class.GShowTypeOf (GHC.Generics.D1 c f)
instance NoThunks.Class.GWRecordField f 'GHC.Types.True
instance NoThunks.Class.GWNoThunks '[] f => NoThunks.Class.GWRecordField f 'GHC.Types.False
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Generics.D1 c f)
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Generics.C1 c f)
instance NoThunks.Class.GWNoThunks a f => NoThunks.Class.GWNoThunks a (GHC.Generics.S1 ('GHC.Generics.MetaSel 'GHC.Maybe.Nothing su ss ds) f)
instance (NoThunks.Class.GWNoThunks a f, NoThunks.Class.GWNoThunks a g) => NoThunks.Class.GWNoThunks a (f GHC.Generics.:*: g)
instance (NoThunks.Class.GWNoThunks a f, NoThunks.Class.GWNoThunks a g) => NoThunks.Class.GWNoThunks a (f GHC.Generics.:+: g)
instance NoThunks.Class.GWNoThunks a GHC.Generics.U1
instance NoThunks.Class.GWNoThunks a GHC.Generics.V1
