-- 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
--   
--   
--   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 or whereFrom if available), 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)
($dmwNoThunks) :: (NoThunks a, Generic a, GWNoThunks ('[] :: [Symbol]) (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
($dmshowTypeOf) :: (NoThunks a, Generic a, GShowTypeOf (Rep a)) => Proxy a -> String

-- | Information about unexpected thunks
--   
--   ThunkInfo contains either precise Info about the thunk location
--   or Context to make it easier to debug space leaks. Info
--   is available if
--   
--   
--   
- GHC-9.4 or newer is used,
--   
- the code is compiled with -finfo-table-map and is
--   improved if -fdistinct-constructor-tables is used as
--   well.
--   
--   
--   The Context argument is intended to give a clue to add
--   debugging. For example, suppose we have something of type (Int,
--   [Int]). The various contexts we might get are
--   
--   
--   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
--   
--   
--   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 ThunkInfo either from Context or information
--   provided by GHC about a (see whereFrom).
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
--   
--   
--   ["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]

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