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

-- | GHC plugin to do inspection testing
--   
--   Some carefully crafted libraries make promises to their users beyond
--   functionality and performance.
--   
--   Examples are: Fusion libraries promise intermediate data structures to
--   be eliminated. Generic programming libraries promise that the generic
--   implementation is identical to the hand-written one. Some libraries
--   may promise allocation-free or branch-free code.
--   
--   Conventionally, the modus operandi in all these cases is that the
--   library author manually inspects the (intermediate or final) code
--   produced by the compiler. This is not only tedious, but makes it very
--   likely that some change, either in the library itself or the
--   surrounding eco-system, breaks the library’s promised without anyone
--   noticing.
--   
--   This package provides a disciplined way of specifying such properties,
--   and have them checked by the compiler. This way, this checking can be
--   part of the ususal development cycle and regressions caught early.
--   
--   See the documentation in Test.Inspection or the project webpage
--   for more examples and more information.
@package inspection-testing
@version 0.6.2

-- | This module supports the accompanying GHC plugin
--   Test.Inspection.Plugin and adds to GHC the ability to do
--   inspection testing.
module Test.Inspection

-- | As seen in the example above, the entry point to inspection testing is
--   the inspect function, to which you pass an Obligation.
--   It will report test failures at compile time.
inspect :: Obligation -> Q [Dec]

-- | This is a variant of inspect that allows compilation to succeed
--   in any case, and instead indicates the result as a value of type
--   Result, which allows seamless integration into test frameworks.
--   
--   This variant ignores the expectFail field of the obligation.
--   Instead, it is expected that you use the corresponding functionality
--   in your test framework (e.g. tasty-expected-failure)
inspectTest :: Obligation -> Q Exp

-- | The result of inspectTest, which has a more or less helpful
--   text message
data Result
Failure :: String -> Result
Success :: String -> Result

-- | This data type describes an inspection testing obligation.
--   
--   It is recommended to build it using mkObligation, for backwards
--   compatibility when new fields are added. You can also use the more
--   mnemonic convenience functions like (===) or hasNoType.
--   
--   The obligation needs to be passed to inspect or
--   inspectTest.
data Obligation
Obligation :: Name -> Property -> Maybe String -> Bool -> Maybe Loc -> Maybe String -> Obligation

-- | The target of a test obligation; invariably the name of a local
--   definition. To get the name of a function foo, write
--   'foo. This requires {-# LANGUAGE TemplateHaskell
--   #-}.
[target] :: Obligation -> Name

-- | The property of the target to be checked.
[property] :: Obligation -> Property

-- | An optional name for the test
[testName] :: Obligation -> Maybe String

-- | Do we expect this property to fail? (Only used by inspect, not
--   by inspectTest)
[expectFail] :: Obligation -> Bool

-- | The source location where this obligation is defined. This is filled
--   in by inspect.
[srcLoc] :: Obligation -> Maybe Loc

-- | If this is Nothing, then report errors during compilation.
--   Otherwise, update the top-level definition with this name.
[storeResult] :: Obligation -> Maybe String

-- | Creates an inspection obligation for the given function name with
--   default values for the optional fields.
mkObligation :: Name -> Property -> Obligation

-- | Equivalence of terms.
data Equivalence

-- | strict term equality
StrictEquiv :: Equivalence

-- | ignore types and hpc ticks during the comparison
IgnoreTypesAndTicksEquiv :: Equivalence

-- | allow permuted let bindings, ignore types and hpc tick during
--   comparison
UnorderedLetsEquiv :: Equivalence

-- | Properties of the obligation target to be checked.
data Property

-- | Are the two functions equal?
--   
--   More precisely: f is equal to g if either the
--   definition of f is f = g, or the definition of
--   g is g = f, or if the definitions are f = e
--   and g = e.
--   
--   In general f and g need to be defined in this
--   module, so that their actual defintions can be inspected.
--   
--   The Equivalence indicates how strict to check for equality
EqualTo :: Name -> Equivalence -> Property

-- | Do none of these types appear anywhere in the definition of the
--   function (neither locally bound nor passed as arguments)
NoTypes :: [Name] -> Property

-- | Does this function perform no heap allocations.
NoAllocation :: Property

-- | Does this value contain dictionaries (except of the listed
--   classes).
NoTypeClasses :: [Name] -> Property

-- | Does not contain this value (in terms or patterns)
NoUseOf :: [Name] -> Property

-- | Always satisfied, but dumps the value in non-quiet mode.
CoreOf :: Property

-- | Declare two functions to be equal (see EqualTo)
(===) :: Name -> Name -> Obligation
infix 9 ===

-- | Declare two functions to be equal, but ignoring type lambdas, type
--   arguments, type casts and hpc ticks (see EqualTo). Note that
--   -fhpc can prevent some optimizations; build without for more
--   reliable analysis.
(==-) :: Name -> Name -> Obligation
infix 9 ==-

-- | Declare two functions to be equal, but expect the test to fail (see
--   EqualTo and expectFail) (This is useful for
--   documentation purposes, or as a TODO list.)
(=/=) :: Name -> Name -> Obligation
infix 9 =/=

-- | Declare two functions to be equal up to types (see (==-)), but
--   expect the test to fail (see expectFail).
(=/-) :: Name -> Name -> Obligation
infix 9 =/-

-- | Declare two functions to be equal as (==-) but also
--   ignoring let bindings ordering (see EqualTo).
(==~) :: Name -> Name -> Obligation
infix 9 ==~

-- | Declare two functions to be equal up to let binding ordering (see
--   (==~)), but expect the test to fail (see expectFail).
(=/~) :: Name -> Name -> Obligation
infix 9 =/~

-- | Declare that in a function’s implementation, the given type does not
--   occur.
--   
--   More precisely: No locally bound variable (let-bound, lambda-bound or
--   pattern-bound) has a type that contains the given type constructor.
--   
--   
--   inspect $ fusedFunction `hasNoType` ''[]
--   
hasNoType :: Name -> Name -> Obligation

-- | Declare that a function’s implementation does not contain any generic
--   types. This is just hasNoType applied to the usual type
--   constructors used in GHC.Generics.
--   
--   
--   inspect $ hasNoGenerics genericFunction
--   
hasNoGenerics :: Name -> Obligation

-- | Declare that a function's implementation does not include
--   dictionaries.
--   
--   More precisely: No locally bound variable (let-bound, lambda-bound or
--   pattern-bound) has a type that contains a type that mentions a type
--   class.
--   
--   
--   inspect $ hasNoTypeClasses specializedFunction
--   
hasNoTypeClasses :: Name -> Obligation

-- | A variant of hasNoTypeClasses, which white-lists some
--   type-classes.
--   
--   
--   inspect $ fieldLens `hasNoTypeClassesExcept` [''Functor]
--   
hasNoTypeClassesExcept :: Name -> [Name] -> Obligation

-- | Declare that a function's implementation does not use the given
--   variable (either in terms or -- if it is a constructor -- in
--   patterns).
--   
--   
--   inspect $ foo `doesNotUse` 'error
--   
doesNotUse :: Name -> Name -> Obligation

-- | Dump the Core of the value.
--   
--   
--   inspect $ coreOf 'foo
--   
--   
--   This is useful when you need to inspect some values manually.
coreOf :: Name -> Obligation
instance GHC.Internal.Data.Data.Data Test.Inspection.Equivalence
instance GHC.Internal.Data.Data.Data Test.Inspection.Obligation
instance GHC.Internal.Data.Data.Data Test.Inspection.Property
instance GHC.Internal.Show.Show Test.Inspection.Result

-- | This module implements some analyses of Core expressions necessary for
--   Test.Inspection. Normally, users of this package can ignore
--   this module.
module Test.Inspection.Core

-- | Selects those bindings that define the given variable (with this
--   variable first)
slice :: [(Var, CoreExpr)] -> Var -> Slice

-- | Pretty-print a slice
pprSlice :: Slice -> SDoc

-- | Pretty-print two slices, after removing variables occurring in both
pprSliceDifference :: Slice -> Slice -> SDoc

-- | This is a heuristic, which only works if both slices have auxiliary
--   variables in the right order. (This is mostly to work-around the buggy
--   CSE in GHC-8.0) It also breaks if there is shadowing.
eqSlice :: Equivalence -> Slice -> Slice -> Bool

-- | Like eqSlice but also returns an explanation of inequality.
eqSlice' :: Equivalence -> Slice -> Slice -> Either SDoc ()

-- | Returns True if the given core expression mentions no type
--   constructor anywhere that has the given name.
freeOfType :: Slice -> [Name] -> Maybe (Var, CoreExpr)

-- | Returns True if the given core expression mentions no term
--   variable anywhere that has the given name.
freeOfTerm :: Slice -> [Name] -> Maybe (Var, CoreExpr)

-- | True if the given variable binding does not allocate, if called fully
--   satisfied.
--   
--   It currently does not look through function calls, which of course
--   could allocate. It should probably at least look through local
--   function calls.
--   
--   The variable is important to know the arity of the function.
doesNotAllocate :: Slice -> Maybe (Var, CoreExpr)
doesNotContainTypeClasses :: Slice -> [Name] -> Maybe (Var, CoreExpr, [TyCon])

-- | See Test.Inspection.
module Test.Inspection.Plugin

-- | The plugin. It supports some options:
--   
--   
--   
- -fplugin-opt=Test.Inspection.Plugin:keep-going to keep
--   building despite failing obligations
--   
- -fplugin-opt=Test.Inspection.Plugin:keep-going-O0 to keep
--   building despite failing obligations, when optimisations are off
--   
- -fplugin-opt=Test.Inspection.Plugin:skip-O0 to skip
--   performing inspections when optimisations are off
--   
- -fplugin-opt=Test.Inspection.Plugin:quiet to be silent if
--   all obligations are fulfilled
--   
--   
--   It makes sense to enable only one of keep-going,
--   keep-going-O0 and skip-O0 at a time.
--   skip-O0 is useful when working with GHCi, to suppress
--   inspection failure messages and eliminate the overhead of inspection
--   when loading.
plugin :: Plugin
checkProperty :: ModGuts -> Name -> Property -> CoreM CheckResult
data CheckResult
ResSuccess :: CheckResult
ResSuccessWithMessage :: SDoc -> CheckResult
ResFailure :: SDoc -> CheckResult
prettyProperty :: (Name -> String) -> Name -> Property -> String
instance GHC.Internal.Enum.Bounded Test.Inspection.Plugin.Stat
instance GHC.Internal.Enum.Enum Test.Inspection.Plugin.Stat
instance GHC.Classes.Eq Test.Inspection.Plugin.ReportingMode
instance GHC.Classes.Eq Test.Inspection.Plugin.Stat
instance GHC.Classes.Eq Test.Inspection.Plugin.UponFailure
instance GHC.Classes.Ord Test.Inspection.Plugin.Stat
