-- 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.3 -- | 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 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 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 -- memonic convenience functions like '(===)' or hasNoType. -- -- The obligation needs to be passed to inspect. 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 -- | 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. -- -- If the boolean flag is true, then ignore types during the comparison. EqualTo :: Name -> Bool -> Property -- | Do none of these types 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 -- | 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 and type casts (see EqualTo) (==-) :: Name -> Name -> Obligation infix 9 ==- -- | Reclare 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 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 asNoType 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 instance GHC.Show.Show Test.Inspection.Result instance Data.Data.Data Test.Inspection.Obligation instance Data.Data.Data Test.Inspection.Property -- | This module implements some of analyses of Core expressions necessary -- for Test.Inspection. Normally, users of this pacakge can ignore -- this module. module Test.Inspection.Core -- | Selects those bindings that define the given variable 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 auxillary -- 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 :: Bool -> Slice -> Slice -> Bool -- | Returns True if the given core expression mentions no type -- constructor anywhere that has the given name. freeOfType :: 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) -- | See Test.Inspection. module Test.Inspection.Plugin -- | The plugin. It supports the option -- -fplugin-opt=Test.Inspection.Plugin:keep-going to ignore a -- failing build. plugin :: Plugin instance GHC.Enum.Bounded Test.Inspection.Plugin.Stat instance GHC.Classes.Ord Test.Inspection.Plugin.Stat instance GHC.Classes.Eq Test.Inspection.Plugin.Stat instance GHC.Enum.Enum Test.Inspection.Plugin.Stat instance GHC.Classes.Eq Test.Inspection.Plugin.UponFailure