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

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
--   
--   
--   noThunks ctxt x == Nothing
--   
--   
--   if and only if
--   
--   
--   checkContainsThunks x
--   
--   
--   For some datatypes however, some thunks are expected. For example, the
--   internal fingertree Sequence might contain thunks (this is
--   important for the asymptotic complexity of this data structure).
--   However, we should still check that the values 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
--   noThunks to force such "expected thunks", as long as it always
--   reports the unexpected thunks.
--   
--   The default implementation of noThunks checks that the argument
--   is in WHNF, and if so, adds the type into the context (using
--   showTypeOf), and calls wNoThunks. See ThunkInfo
--   for a detailed discussion of the type context.
--   
--   See also discussion of caveats listed for checkContainsThunks.
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 inside
--   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 inside
--   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 a (to add to the context)
--   
--   We try hard to avoid Typeable constraints in this module: there
--   are types with no Typeable instance but with a NoThunks
--   instance (most important example are types such as ST s which
--   rely on parametric polymorphism). By default we should therefore only
--   show the "outer layer"; for example, if we have a type
--   
--   
--   Seq (ST s ())
--   
--   
--   then showTypeOf should just give Seq, leaving it up to
--   the instance for ST to decide how to implement
--   showTypeOf; this keeps things compositional. The default
--   implementation does precisely this using the metadata that GHC
--   Generics provides.
--   
--   For convenience, however, some of the deriving via newtype
--   wrappers we provide do depend on Typeable; see below.
showTypeOf :: NoThunks a => Proxy a -> String

-- | Show type a (to add to the context)
--   
--   We try hard to avoid Typeable constraints in this module: there
--   are types with no Typeable instance but with a NoThunks
--   instance (most important example are types such as ST s which
--   rely on parametric polymorphism). By default we should therefore only
--   show the "outer layer"; for example, if we have a type
--   
--   
--   Seq (ST s ())
--   
--   
--   then showTypeOf should just give Seq, leaving it up to
--   the instance for ST to decide how to implement
--   showTypeOf; this keeps things compositional. The default
--   implementation does precisely this using the metadata that GHC
--   Generics provides.
--   
--   For convenience, however, some of the deriving via newtype
--   wrappers we provide do depend on Typeable; 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
--   
--   
--   ["Int", "(,)", "Map", "AppState"]
--   
--   
--   telling you that you have an AppState containing a
--   Map containing a pair, all of which weren't thunks (were in
--   WHNF), but that pair contained an Int which was a thunk.
type Context = [String]

-- | Call noThunks in a pure context (relies on
--   unsafePerformIO).
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 noThunksInKeysAndValues
noThunksInValues :: NoThunks a => Context -> [a] -> IO (Maybe ThunkInfo)

-- | Variant on noThunksInValues 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 deriving via 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 (a -> b) for detailed
--   discussion. This should be used sparingly.
--   
--   Example:
--   
--   
--   deriving via OnlyCheckWhnf T instance NoThunks T
--   
newtype OnlyCheckWhnf a
OnlyCheckWhnf :: a -> OnlyCheckWhnf a

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

-- | Newtype wrapper for use with deriving via 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
--   anywhere. Since we can do this without any type classes
--   instances, this is useful for types that contain fields for which
--   NoThunks instances are not available.
--   
--   Since the primary use case for InspectHeap then is to give
--   instances for NoThunks from third party libraries, we also
--   don't want to rely on a Generic instance, which may likewise
--   not be available. Instead, we will rely on Typeable, which is
--   available for all types. However, as showTypeOf
--   explains, requiring Typeable may not always be suitable; if it
--   isn't, InspectHeapNamed can be used.
--   
--   Example:
--   
--   
--   deriving via InspectHeap T instance NoThunks T
--   
newtype InspectHeap a
InspectHeap :: a -> InspectHeap a

-- | Variant on InspectHeap that does not depend on Typeable.
--   
--   
--   deriving via InspectHeapNamed "T" T instance NoUnexpecedThunks T
--   
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 VERY sparingly, and should ONLY be
--   used on values (or, even rarer, types) which you are SURE
--   cannot retain any data that they shouldn't. Bear in mind allowing a
--   value of type T to be a thunk might cause a value of type
--   S to be retained if T was computed from S.
newtype AllowThunk a
AllowThunk :: a -> AllowThunk a

-- | Newtype wrapper for records where some of the fields are allowed to be
--   thunks.
--   
--   Example:
--   
--   
--   deriving via AllowThunksIn '["foo","bar"] T instance NoThunks T
--   
--   
--   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 a argument records which record fields are allowed to
--   contain thunks; see AllowThunksIn and GWRecordField,
--   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 (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) => 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 Data.Void.Void
instance NoThunks.Class.NoThunks ()
instance NoThunks.Class.NoThunks a => NoThunks.Class.NoThunks [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
