packages feed

ghc-typelits-presburger 0.3.0.1 → 0.4.0.0

raw patch · 8 files changed

+461/−270 lines, 8 filesdep +tastydep +tasty-discoverdep +tasty-expected-failuredep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: tasty, tasty-discover, tasty-expected-failure, tasty-hunit, text

Dependency ranges changed: base

API changes (from Hackage documentation)

- GHC.TypeLits.Presburger.Compat: [TcPlugin] :: forall s. () => {tcPluginInit :: TcPluginM s, tcPluginSolve :: s -> TcPluginSolver, tcPluginStop :: s -> TcPluginM ()} -> TcPlugin
- GHC.TypeLits.Presburger.Compat: data PredTree
- GHC.TypeLits.Presburger.Compat: injTyVarsOfType :: TcTauType -> TcTyVarSet
- GHC.TypeLits.Presburger.Compat: injTyVarsOfTypes :: [Type] -> VarSet
- GHC.TypeLits.Presburger.Compat: makeInjectivityErrors :: () => CoAxiom br -> CoAxBranch -> [Bool] -> [CoAxBranch] -> [(SDoc, SrcSpan)]
- GHC.TypeLits.Presburger.Compat: makeRecoveryTyCon :: TyCon -> TyCon
- GHC.TypeLits.Presburger.Compat: mightBeUnsaturatedTyCon :: TyCon -> Bool
- GHC.TypeLits.Presburger.Compat: tcFlavourCanBeUnsaturated :: TyConFlavour -> Bool
+ GHC.TypeLits.Presburger.Compat: Int16Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: Int32Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: Int8Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: TcPlugin :: TcPluginM s -> (s -> TcPluginSolver) -> (s -> TcPluginM ()) -> TcPlugin
+ GHC.TypeLits.Presburger.Compat: Word16Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: Word32Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: Word8Rep :: PrimRep
+ GHC.TypeLits.Presburger.Compat: [dynflagsPlugin] :: Plugin -> [CommandLineOption] -> DynFlags -> IO DynFlags
+ GHC.TypeLits.Presburger.Compat: [ft_af] :: Type -> AnonArgFlag
+ GHC.TypeLits.Presburger.Compat: [ft_arg] :: Type -> Type
+ GHC.TypeLits.Presburger.Compat: [ft_res] :: Type -> Type
+ GHC.TypeLits.Presburger.Compat: [holeFitPlugin] :: Plugin -> HoleFitPlugin
+ GHC.TypeLits.Presburger.Compat: [nt_lev_poly] :: AlgTyConRhs -> Bool
+ GHC.TypeLits.Presburger.Compat: [tcPluginInit] :: TcPlugin -> TcPluginM s
+ GHC.TypeLits.Presburger.Compat: [tcPluginSolve] :: TcPlugin -> s -> TcPluginSolver
+ GHC.TypeLits.Presburger.Compat: [tcPluginStop] :: TcPlugin -> s -> TcPluginM ()
+ GHC.TypeLits.Presburger.Compat: data Pred
+ GHC.TypeLits.Presburger.Compat: defaultRecTcMaxBound :: Int
+ GHC.TypeLits.Presburger.Compat: mkRequiredTyConBinder :: TyCoVarSet -> TyVar -> TyConBinder
+ GHC.TypeLits.Presburger.Compat: mustBeSaturated :: TyCon -> Bool
+ GHC.TypeLits.Presburger.Compat: noTcTyConScopedTyVars :: [(Name, TcTyVar)]
+ GHC.TypeLits.Presburger.Compat: primRepCompatible :: DynFlags -> PrimRep -> PrimRep -> Bool
+ GHC.TypeLits.Presburger.Compat: primRepsCompatible :: DynFlags -> [PrimRep] -> [PrimRep] -> Bool
+ GHC.TypeLits.Presburger.Compat: reportConflictingInjectivityErrs :: TyCon -> [CoAxBranch] -> CoAxBranch -> TcM ()
+ GHC.TypeLits.Presburger.Compat: reportInjectivityErrors :: forall (br :: BranchFlag). DynFlags -> CoAxiom br -> CoAxBranch -> [Bool] -> TcM ()
+ GHC.TypeLits.Presburger.Compat: setRecTcMaxBound :: Int -> RecTcChecker -> RecTcChecker
+ GHC.TypeLits.Presburger.Compat: setTcTyConKind :: TyCon -> Kind -> TyCon
+ GHC.TypeLits.Presburger.Compat: tyConFlavourAssoc_maybe :: TyConFlavour -> Maybe TyCon
+ GHC.TypeLits.Presburger.Compat: type PredTree = Pred
+ GHC.TypeLits.Presburger.Compat: type TyConTyCoBinder = VarBndr TyCoVar TyConBndrVis
- GHC.TypeLits.Presburger.Compat: AnonTCB :: TyConBndrVis
+ GHC.TypeLits.Presburger.Compat: AnonTCB :: AnonArgFlag -> TyConBndrVis
- GHC.TypeLits.Presburger.Compat: ClassPred :: Class -> [Type] -> PredTree
+ GHC.TypeLits.Presburger.Compat: ClassPred :: Class -> [Type] -> Pred
- GHC.TypeLits.Presburger.Compat: DataFamilyFlavour :: Bool -> TyConFlavour
+ GHC.TypeLits.Presburger.Compat: DataFamilyFlavour :: Maybe TyCon -> TyConFlavour
- GHC.TypeLits.Presburger.Compat: EqPred :: EqRel -> Type -> Type -> PredTree
+ GHC.TypeLits.Presburger.Compat: EqPred :: EqRel -> Type -> Type -> Pred
- GHC.TypeLits.Presburger.Compat: ForAllPred :: [TyVarBinder] -> [PredType] -> PredType -> PredTree
+ GHC.TypeLits.Presburger.Compat: ForAllPred :: [TyCoVarBinder] -> [PredType] -> PredType -> Pred
- GHC.TypeLits.Presburger.Compat: ForAllTy :: {-# UNPACK #-} !TyVarBinder -> Type -> Type
+ GHC.TypeLits.Presburger.Compat: ForAllTy :: {-# UNPACK #-} !TyCoVarBinder -> Type -> Type
- GHC.TypeLits.Presburger.Compat: FunTy :: Type -> Type -> Type
+ GHC.TypeLits.Presburger.Compat: FunTy :: AnonArgFlag -> Type -> Type -> Type
- GHC.TypeLits.Presburger.Compat: IrredPred :: PredType -> PredTree
+ GHC.TypeLits.Presburger.Compat: IrredPred :: PredType -> Pred
- GHC.TypeLits.Presburger.Compat: NewTyCon :: DataCon -> Type -> ([TyVar], Type) -> CoAxiom Unbranched -> AlgTyConRhs
+ GHC.TypeLits.Presburger.Compat: NewTyCon :: DataCon -> Type -> ([TyVar], Type) -> CoAxiom Unbranched -> Bool -> AlgTyConRhs
- GHC.TypeLits.Presburger.Compat: OpenTypeFamilyFlavour :: Bool -> TyConFlavour
+ GHC.TypeLits.Presburger.Compat: OpenTypeFamilyFlavour :: Maybe TyCon -> TyConFlavour
- GHC.TypeLits.Presburger.Compat: Plugin :: CorePlugin -> TcPlugin -> ([CommandLineOption] -> IO PluginRecompile) -> ([CommandLineOption] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule) -> ([CommandLineOption] -> TcGblEnv -> HsGroup GhcRn -> TcM (TcGblEnv, HsGroup GhcRn)) -> ([CommandLineOption] -> ModSummary -> TcGblEnv -> TcM TcGblEnv) -> ([CommandLineOption] -> LHsExpr GhcTc -> TcM (LHsExpr GhcTc)) -> (forall lcl. () => [CommandLineOption] -> ModIface -> IfM lcl ModIface) -> Plugin
+ GHC.TypeLits.Presburger.Compat: Plugin :: CorePlugin -> TcPlugin -> HoleFitPlugin -> ([CommandLineOption] -> DynFlags -> IO DynFlags) -> ([CommandLineOption] -> IO PluginRecompile) -> ([CommandLineOption] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule) -> ([CommandLineOption] -> TcGblEnv -> HsGroup GhcRn -> TcM (TcGblEnv, HsGroup GhcRn)) -> ([CommandLineOption] -> ModSummary -> TcGblEnv -> TcM TcGblEnv) -> ([CommandLineOption] -> LHsExpr GhcTc -> TcM (LHsExpr GhcTc)) -> (forall lcl. () => [CommandLineOption] -> ModIface -> IfM lcl ModIface) -> Plugin
- GHC.TypeLits.Presburger.Compat: expandSynTyCon_maybe :: () => TyCon -> [tyco] -> Maybe ([(TyVar, tyco)], Type, [tyco])
+ GHC.TypeLits.Presburger.Compat: expandSynTyCon_maybe :: TyCon -> [tyco] -> Maybe ([(TyVar, tyco)], Type, [tyco])
- GHC.TypeLits.Presburger.Compat: isInvisibleTyConBinder :: () => TyVarBndr tv TyConBndrVis -> Bool
+ GHC.TypeLits.Presburger.Compat: isInvisibleTyConBinder :: VarBndr tv TyConBndrVis -> Bool
- GHC.TypeLits.Presburger.Compat: isVisibleTyConBinder :: () => TyVarBndr tv TyConBndrVis -> Bool
+ GHC.TypeLits.Presburger.Compat: isVisibleTyConBinder :: VarBndr tv TyConBndrVis -> Bool
- GHC.TypeLits.Presburger.Compat: mkAnonTyConBinder :: TyVar -> TyConBinder
+ GHC.TypeLits.Presburger.Compat: mkAnonTyConBinder :: AnonArgFlag -> TyVar -> TyConBinder
- GHC.TypeLits.Presburger.Compat: mkAnonTyConBinders :: [TyVar] -> [TyConBinder]
+ GHC.TypeLits.Presburger.Compat: mkAnonTyConBinders :: AnonArgFlag -> [TyVar] -> [TyConBinder]
- GHC.TypeLits.Presburger.Compat: mkPromotedDataCon :: DataCon -> Name -> TyConRepName -> [TyConBinder] -> Kind -> [Role] -> RuntimeRepInfo -> TyCon
+ GHC.TypeLits.Presburger.Compat: mkPromotedDataCon :: DataCon -> Name -> TyConRepName -> [TyConTyCoBinder] -> Kind -> [Role] -> RuntimeRepInfo -> TyCon
- GHC.TypeLits.Presburger.Compat: mkTcTyCon :: Name -> SDoc -> [TyConBinder] -> Kind -> [(Name, TcTyVar)] -> TyConFlavour -> TyCon
+ GHC.TypeLits.Presburger.Compat: mkTcTyCon :: Name -> [TyConBinder] -> Kind -> [(Name, TcTyVar)] -> Bool -> TyConFlavour -> TyCon
- GHC.TypeLits.Presburger.Compat: splitTyConApp_maybe :: HasDebugCallStack -> Type -> Maybe (TyCon, [Type])
+ GHC.TypeLits.Presburger.Compat: splitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])
- GHC.TypeLits.Presburger.Compat: tcExtendLocalFamInstEnv :: () => [FamInst] -> TcM a -> TcM a
+ GHC.TypeLits.Presburger.Compat: tcExtendLocalFamInstEnv :: [FamInst] -> TcM a -> TcM a
- GHC.TypeLits.Presburger.Compat: tcInferApps :: TcTyMode -> Maybe (VarEnv Kind) -> LHsType GhcRn -> TcType -> TcKind -> [LHsType GhcRn] -> TcM (TcType, [TcType], TcKind)
+ GHC.TypeLits.Presburger.Compat: tcInferApps :: TcTyMode -> LHsType GhcRn -> TcType -> [LHsTypeArg GhcRn] -> TcM (TcType, TcKind)
- GHC.TypeLits.Presburger.Compat: tyConAssoc_maybe :: TyCon -> Maybe Class
+ GHC.TypeLits.Presburger.Compat: tyConAssoc_maybe :: TyCon -> Maybe TyCon
- GHC.TypeLits.Presburger.Compat: type TyConBinder = TyVarBndr TyVar TyConBndrVis
+ GHC.TypeLits.Presburger.Compat: type TyConBinder = VarBndr TyVar TyConBndrVis
- GHC.TypeLits.Presburger.Compat: typeKind :: HasDebugCallStack -> Type -> Kind
+ GHC.TypeLits.Presburger.Compat: typeKind :: HasDebugCallStack => Type -> Kind
- GHC.TypeLits.Presburger.Types: infix 4 :>=
+ GHC.TypeLits.Presburger.Types: infix 4 :>
- GHC.TypeLits.Presburger.Types: infixl 6 :-
+ GHC.TypeLits.Presburger.Types: infixl 6 :+

Files

examples/simple-arith-core.hs view
@@ -1,6 +1,15 @@-{-# LANGUAGE CPP, DataKinds, EmptyCase, FlexibleContexts, GADTs, LambdaCase #-}-{-# LANGUAGE PolyKinds, ScopedTypeVariables, TypeFamilies, TypeInType       #-}-{-# LANGUAGE TypeOperators, UndecidableInstances                            #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -dcore-lint #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.Presburger #-} @@ -9,21 +18,25 @@ #endif  module Main where+ import Data.Proxy import Data.Type.Equality import GHC.TypeLits-import Proof.Propositional (Empty (..), withEmpty)-import Proof.Propositional (IsTrue (Witness))+import Proof.Propositional (Empty (..), IsTrue (Witness), withEmpty)  type n <=! m = IsTrue (n <=? m)+ infix 4 <=!  type family Length (as :: [k]) where   Length '[] = 0   Length (x ': xs) = 1 + Length xs -natLen :: (Length xs <= Length ys)-       => proxy xs -> proxy ys -> (Length ys - Length xs) + Length xs :~: Length ys+natLen ::+  (Length xs <= Length ys) =>+  proxy xs ->+  proxy ys ->+  (Length ys - Length xs) + Length xs :~: Length ys natLen _ _ = Refl  natLeqZero' :: (n <= 0) => proxy n -> n :~: 0@@ -35,15 +48,14 @@ leqEquiv :: (n <= m) => p n -> p m -> IsTrue (n <=? m) leqEquiv _ _ = Witness - plusLeq :: (n <= m) => proxy (n :: Nat) -> proxy m -> ((m - n) + n :~: m) plusLeq _ _ = Refl  minusLeq :: (n <= m) => proxy (n :: Nat) -> proxy m -> IsTrue ((m - n) + n <=? m) minusLeq _ _ = Witness -absurdTrueFalse :: ('True :~: 'False) -> a-absurdTrueFalse = \case {}+absurdTrueFalse :: ( 'True :~: 'False) -> a+absurdTrueFalse = \case  #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ > 802 hoge :: proxy n -> IsTrue (n + 1 <=? n) -> a@@ -56,16 +68,14 @@ barResult :: () barResult = bar (Proxy :: Proxy 2) - trans :: proxy n -> proxy m -> n <=! m -> (n + 1) <=! (m + 1)-trans _ _  Witness = Witness+trans _ _ Witness = Witness  eqv :: proxy n -> proxy m -> (n <=? m) :~: ((n + 1) <=? (m + 1)) eqv _ _ = Refl  predSucc :: forall proxy n. Empty (n <=! 0) => proxy n -> IsTrue (n + 1 <=? 2 * n) predSucc _ = Witness-  succLEqLTSucc :: pxy m -> CmpNat 0 (m + 1) :~: 'LT succLEqLTSucc _ = Refl
ghc-typelits-presburger.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 3e336ef49eb47a4a5b2a74bdb84e17585fa0870e8c22e48ebb8402904c01ffe7+-- hash: c960b466954cc5f717d05e796b5bd46864fa0d34fe74e43583e277fb61613376  name:           ghc-typelits-presburger-version:        0.3.0.1+version:        0.4.0.0 synopsis:       Presburger Arithmetic Solver for GHC Type-level natural numbers. description:    @ghc-typelits-presburger@ augments GHC type-system with Presburger                 Arithmetic Solver for Type-level natural numbers.@@ -29,7 +29,7 @@ copyright:      2015 (c) Hiromi ISHII license:        BSD3 license-file:   LICENSE-tested-with:    GHC==8.4.3 GHC==8.6.3 GHC==8.8.3 GHC==8.10.1+tested-with:    GHC==8.4.3 GHC==8.6.3 GHC==8.8.3 GHC==8.10.3 build-type:     Simple  source-repository head@@ -77,4 +77,29 @@     , ghc-typelits-presburger   if !(flag(examples))     buildable: False+  default-language: Haskell2010++test-suite test-typeltis-presburger+  type: exitcode-stdio-1.0+  main-is: test.hs+  other-modules:+      ErrorsNoPlugin+      ErrorsWithPlugin+      GHC.TypeLits.PresburgerSpec+      Shared+      Paths_ghc_typelits_presburger+  hs-source-dirs:+      test+  ghc-options: -Wall -Wno-dodgy-imports+  build-tool-depends:+      tasty-discover:tasty-discover+  build-depends:+      base+    , equational-reasoning+    , ghc-typelits-presburger+    , tasty+    , tasty-discover+    , tasty-expected-failure+    , tasty-hunit+    , text   default-language: Haskell2010
src/GHC/TypeLits/Presburger/Types.hs view
@@ -1,49 +1,71 @@-{-# LANGUAGE BangPatterns, CPP, DataKinds, FlexibleContexts               #-}-{-# LANGUAGE FlexibleInstances, LambdaCase, MultiWayIf, OverloadedStrings #-}-{-# LANGUAGE PatternGuards, RankNTypes, TypeOperators, ViewPatterns       #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+ -- | Since 0.3.0.0 module GHC.TypeLits.Presburger.Types-  ( pluginWith-  , defaultTranslation-  , Translation(..), ParseEnv, Machine-  , module Data.Integer.SAT-  ) where-import           Class                          (classTyCon)-import           Control.Applicative            ((<|>))-import           Control.Arrow                  (second)-import           Outputable (showSDocUnsafe)  -import           Control.Monad                  (forM_, guard, mzero, unless)-import           Control.Monad.State.Class-import           Control.Monad.Trans.Class-import           Control.Monad.Trans.Maybe      (MaybeT (..))-import           Control.Monad.Trans.RWS.Strict (runRWS, tell)-import           Control.Monad.Trans.State      (StateT, runStateT)-import           Data.Foldable                  (asum)-import           Data.Integer.SAT               (Expr (..), Prop (..), PropSet,-                                                 assert)-import           Data.Integer.SAT               (checkSat, noProps, toName)-import qualified Data.Integer.SAT               as SAT-import           Data.List                      (nub)-import qualified Data.Map.Strict                as M-import           Data.Maybe                     (catMaybes, fromMaybe,-                                                 isNothing)-import           Data.Reflection                (Given, give, given)-import qualified Data.Set                       as Set-import           GHC.TypeLits.Presburger.Compat-import           PrelNames-import           TcPluginM                      (lookupOrig, newFlexiTyVar,-                                                 newWanted, tcLookupClass)-import           Type                           (mkTyVarTy)-import           TysWiredIn                     (promotedEQDataCon,-                                                 promotedGTDataCon,-                                                 promotedLTDataCon)+  ( pluginWith,+    defaultTranslation,+    Translation (..),+    ParseEnv,+    Machine,+    module Data.Integer.SAT,+  )+where++import Class (classTyCon)+import Control.Applicative ((<|>))+import Control.Arrow (second)+import Control.Monad (forM_, guard, mzero, unless)+import Control.Monad.State.Class+import Control.Monad.Trans.Class+import Control.Monad.Trans.Maybe (MaybeT (..))+import Control.Monad.Trans.RWS.Strict (runRWS, tell)+import Control.Monad.Trans.State (StateT, runStateT)+import Data.Foldable (asum)+import Data.Integer.SAT (Expr (..), Prop (..), PropSet, assert, checkSat, noProps, toName)+import qualified Data.Integer.SAT as SAT+import Data.List (nub)+import qualified Data.Map.Strict as M+import Data.Maybe+  ( catMaybes,+    fromMaybe,+    isNothing,+  )+import Data.Reflection (Given, give, given)+import qualified Data.Set as Set+import GHC.TypeLits.Presburger.Compat+import Outputable (showSDocUnsafe)+import PrelNames+import TcPluginM+  ( lookupOrig,+    newFlexiTyVar,+    newWanted,+    tcLookupClass,+  )+import Type (mkTyVarTy)+import TysWiredIn+  ( promotedEQDataCon,+    promotedGTDataCon,+    promotedLTDataCon,+  ) #if MIN_VERSION_ghc(8,8,1) import TysWiredIn (eqTyConName) #else import PrelNames (eqTyConName) #endif -import           Var+import Var+ #if MIN_VERSION_ghc(8,6,0) import Plugins (purePlugin) #endif@@ -51,44 +73,46 @@ assert' :: Prop -> PropSet -> PropSet assert' p ps = foldr assert ps (p : varPos)   where-    varPos = [K 0 :<= Var i | i <- varsProp p ]+    varPos = [K 0 :<= Var i | i <- varsProp p]  data Proof = Proved | Disproved [(Int, Integer)]-           deriving (Read, Show, Eq, Ord)+  deriving (Read, Show, Eq, Ord)  isProved :: Proof -> Bool isProved Proved = True-isProved _      = False+isProved _ = False  varsProp :: Prop -> [SAT.Name] varsProp (p :|| q) = nub $ varsProp p ++ varsProp q varsProp (p :&& q) = nub $ varsProp p ++ varsProp q-varsProp (Not p)   = varsProp p+varsProp (Not p) = varsProp p varsProp (e :== v) = nub $ varsExpr e ++ varsExpr v varsProp (e :/= v) = nub $ varsExpr e ++ varsExpr v-varsProp (e :< v)  = nub $ varsExpr e ++ varsExpr v-varsProp (e :> v)  = nub $ varsExpr e ++ varsExpr v+varsProp (e :< v) = nub $ varsExpr e ++ varsExpr v+varsProp (e :> v) = nub $ varsExpr e ++ varsExpr v varsProp (e :<= v) = nub $ varsExpr e ++ varsExpr v varsProp (e :>= v) = nub $ varsExpr e ++ varsExpr v-varsProp _         = []+varsProp _ = []  varsExpr :: Expr -> [SAT.Name]-varsExpr (e :+ v)   = nub $ varsExpr e ++ varsExpr v-varsExpr (e :- v)   = nub $ varsExpr e ++ varsExpr v-varsExpr (_ :* v)   = varsExpr v+varsExpr (e :+ v) = nub $ varsExpr e ++ varsExpr v+varsExpr (e :- v) = nub $ varsExpr e ++ varsExpr v+varsExpr (_ :* v) = varsExpr v varsExpr (Negate e) = varsExpr e-varsExpr (Var i)    = [i]-varsExpr (K _)      = []+varsExpr (Var i) = [i]+varsExpr (K _) = [] varsExpr (If p e v) = nub $ varsProp p ++ varsExpr e ++ varsExpr v-varsExpr (Div e _)  = varsExpr e-varsExpr (Mod e _)  = varsExpr e+varsExpr (Div e _) = varsExpr e+varsExpr (Mod e _) = varsExpr e -data PluginMode = DisallowNegatives-                | AllowNegatives-                deriving (Read, Show, Eq, Ord)+data PluginMode+  = DisallowNegatives+  | AllowNegatives+  deriving (Read, Show, Eq, Ord)  pluginWith :: TcPluginM Translation -> Plugin-pluginWith trans = defaultPlugin+pluginWith trans =+  defaultPlugin     { tcPlugin = Just . presburgerPlugin trans . procOpts #if MIN_VERSION_ghc(8,6,0)     , pluginRecompile = purePlugin@@ -101,11 +125,13 @@  presburgerPlugin :: TcPluginM Translation -> PluginMode -> TcPlugin presburgerPlugin trans mode =-  tracePlugin "typelits-presburger"-  TcPlugin { tcPluginInit  = return ()-           , tcPluginSolve = decidePresburger mode trans-           , tcPluginStop  = const $ return ()-           }+  tracePlugin+    "typelits-presburger"+    TcPlugin+      { tcPluginInit = return ()+      , tcPluginSolve = decidePresburger mode trans+      , tcPluginStop = const $ return ()+      }  testIf :: PropSet -> Prop -> Proof testIf ps q = maybe Proved Disproved $ checkSat (Not q `assert'` ps)@@ -116,21 +142,20 @@ handleSubtraction AllowNegatives p = p handleSubtraction DisallowNegatives p0 =   let (p, _, w) = runRWS (loop p0) () Set.empty-  in foldr (:&&) p w+   in foldr (:&&) p w   where-    loop PTrue     = return PTrue-    loop PFalse    = return PFalse+    loop PTrue = return PTrue+    loop PFalse = return PFalse     loop (q :|| r) = (:||) <$> loop q <*> loop r     loop (q :&& r) = (:&&) <$> loop q <*> loop r-    loop (Not q)   = Not <$> loop q+    loop (Not q) = Not <$> loop q     loop (l :<= r) = (:<=) <$> loopExp l <*> loopExp r-    loop (l :< r)  = (:<) <$> loopExp l <*> loopExp r+    loop (l :< r) = (:<) <$> loopExp l <*> loopExp r     loop (l :>= r) = (:<=) <$> loopExp l <*> loopExp r-    loop (l :> r)  = (:>) <$> loopExp l <*> loopExp r+    loop (l :> r) = (:>) <$> loopExp l <*> loopExp r     loop (l :== r) = (:==) <$> loopExp l <*> loopExp r     loop (l :/= r) = (:/=) <$> loopExp l <*> loopExp r -     withPositive pos = do       dic <- get       unless (Set.member pos dic) $ do@@ -139,46 +164,45 @@       return pos      loopExp e@(Negate _) = withPositive . Negate =<< loopExp e-    loopExp (l :- r)   = do+    loopExp (l :- r) = do       e <- (:-) <$> loopExp l <*> loopExp r       withPositive e-    loopExp (l :+ r)     = (:+) <$> loopExp l <*> loopExp r-    loopExp v@Var {}     = return v+    loopExp (l :+ r) = (:+) <$> loopExp l <*> loopExp r+    loopExp v@Var {} = return v     loopExp (c :* e)       | c > 0 = (c :*) <$> loopExp e       | otherwise = (negate c :*) <$> loopExp (Negate e)     loopExp e@(K _) = return e -data Translation =-  Translation-    { isEmpty     :: [TyCon]-    , isTrue      :: [TyCon]-    , trueData    :: [TyCon]-    , falseData   :: [TyCon]-    , voids       :: [TyCon]-    , tyEq        :: [TyCon]-    , tyEqBool    :: [TyCon]-    , tyEqWitness :: [TyCon]-    , tyNeqBool   :: [TyCon]-    , natPlus     :: [TyCon]-    , natMinus    :: [TyCon]-    , natExp      :: [TyCon]-    , natTimes    :: [TyCon]-    , natLeq      :: [TyCon]-    , natLeqBool  :: [TyCon]-    , natGeq      :: [TyCon]-    , natGeqBool  :: [TyCon]-    , natLt       :: [TyCon]-    , natLtBool   :: [TyCon]-    , natGt       :: [TyCon]-    , natGtBool   :: [TyCon]-    , orderingLT  :: [TyCon]-    , orderingGT  :: [TyCon]-    , orderingEQ  :: [TyCon]-    , natCompare  :: [TyCon]-    , parsePred   :: (Type -> Machine Expr) -> Type -> Machine Prop-    , parseExpr   :: Type -> Machine Expr-    }+data Translation = Translation+  { isEmpty :: [TyCon]+  , isTrue :: [TyCon]+  , trueData :: [TyCon]+  , falseData :: [TyCon]+  , voids :: [TyCon]+  , tyEq :: [TyCon]+  , tyEqBool :: [TyCon]+  , tyEqWitness :: [TyCon]+  , tyNeqBool :: [TyCon]+  , natPlus :: [TyCon]+  , natMinus :: [TyCon]+  , natExp :: [TyCon]+  , natTimes :: [TyCon]+  , natLeq :: [TyCon]+  , natLeqBool :: [TyCon]+  , natGeq :: [TyCon]+  , natGeqBool :: [TyCon]+  , natLt :: [TyCon]+  , natLtBool :: [TyCon]+  , natGt :: [TyCon]+  , natGtBool :: [TyCon]+  , orderingLT :: [TyCon]+  , orderingGT :: [TyCon]+  , orderingEQ :: [TyCon]+  , natCompare :: [TyCon]+  , parsePred :: (Type -> Machine Expr) -> Type -> Machine Prop+  , parseExpr :: Type -> Machine Expr+  }  instance Semigroup Translation where   l <> r =@@ -213,35 +237,36 @@       }  instance Monoid Translation where-  mempty = Translation-    { isEmpty = mempty-    , isTrue = mempty-    , tyEq  = mempty-    , tyEqBool = mempty-    , tyEqWitness = mempty-    , tyNeqBool = mempty-    , voids = mempty-    , natPlus = mempty-    , natMinus = mempty-    , natTimes = mempty-    , natExp = mempty-    , natLeq = mempty-    , natGeq = mempty-    , natLt = mempty-    , natGt = mempty-    , natLeqBool = mempty-    , natGeqBool = mempty-    , natLtBool = mempty-    , natGtBool = mempty-    , orderingLT = mempty-    , orderingGT = mempty-    , orderingEQ = mempty-    , natCompare = mempty-    , trueData = []-    , falseData = []-    , parsePred = const $ const mzero-    , parseExpr = const mzero-    }+  mempty =+    Translation+      { isEmpty = mempty+      , isTrue = mempty+      , tyEq = mempty+      , tyEqBool = mempty+      , tyEqWitness = mempty+      , tyNeqBool = mempty+      , voids = mempty+      , natPlus = mempty+      , natMinus = mempty+      , natTimes = mempty+      , natExp = mempty+      , natLeq = mempty+      , natGeq = mempty+      , natLt = mempty+      , natGt = mempty+      , natLeqBool = mempty+      , natGeqBool = mempty+      , natLtBool = mempty+      , natGtBool = mempty+      , orderingLT = mempty+      , orderingGT = mempty+      , orderingEQ = mempty+      , natCompare = mempty+      , trueData = []+      , falseData = []+      , parsePred = const $ const mzero+      , parseExpr = const mzero+      }  decidePresburger :: PluginMode -> TcPluginM Translation -> () -> [Ct] -> [Ct] -> [Ct] -> TcPluginM TcPluginResult decidePresburger _ genTrans _ gs [] [] = do@@ -251,41 +276,50 @@     ngs <- mapM (\a -> runMachine $ (,) a <$> toPresburgerPred (deconsPred a)) gs     let givens = catMaybes ngs         prems0 = map snd givens-        prems  = foldr assert' noProps prems0+        prems = foldr assert' noProps prems0         (solved, _) = foldr go ([], noProps) givens     if isNothing (checkSat prems)       then return $ TcPluginContradiction gs       else return $ TcPluginOk (map withEv solved) []-    where-      go (ct, p) (ss, prem)-        | Proved <- testIf prem p = (ct : ss, prem)-        | otherwise = (ss, assert' p prem)-decidePresburger mode genTrans _ gs ds ws = do+  where+    go (ct, p) (ss, prem)+      | Proved <- testIf prem p = (ct : ss, prem)+      | otherwise = (ss, assert' p prem)+decidePresburger mode genTrans _ gs _ds ws = do   trans <- genTrans   give trans $ do     gs' <- normaliseGivens gs-    let subst = mkSubstitution (gs' ++ ds)+    let subst = mkSubstitution gs'     tcPluginTrace "pres: Current subst" (ppr subst)     tcPluginTrace "pres: wanteds" $ ppr $ map (subsType subst . deconsPred . subsCt subst) ws     tcPluginTrace "pres: givens" $ ppr $ map (subsType subst . deconsPred) gs-    tcPluginTrace "pres: deriveds" $ ppr $ map deconsPred ds+    tcPluginTrace "pres: deriveds" $ ppr $ map deconsPred _ds     (prems, wants, prems0) <- do-      wants <- catMaybes <$>-              mapM-              (\ct -> runMachine $ (,) ct <$> toPresburgerPred-                  ( subsType subst-                  $ deconsPred $ subsCt subst ct))-              (filter (isWanted . ctEvidence) ws)+      wants <-+        catMaybes+          <$> mapM+            ( \ct ->+                runMachine $+                  (,) ct+                    <$> toPresburgerPred+                      ( subsType subst $+                          deconsPred $ subsCt subst ct+                      )+            )+            (filter (isWanted . ctEvidence) ws) -      resls <- mapM (runMachine . toPresburgerPred . subsType subst . deconsPred)-                      (gs ++ ds)+      resls <-+        mapM+          (runMachine . toPresburgerPred . subsType subst . deconsPred)+          gs       let prems = foldr assert' noProps $ catMaybes resls       return (prems, map (second $ handleSubtraction mode) wants, catMaybes resls)     let solved = map fst $ filter (isProved . testIf prems . snd) wants-        coerced = [(evByFiat "ghc-typelits-presburger" t1 t2, ct)-                  | ct <- solved-                  , EqPred NomEq t1 t2 <- return (classifyPredType $ deconsPred ct)-                  ]+        coerced =+          [ (evByFiat "ghc-typelits-presburger" t1 t2, ct)+          | ct <- solved+          , EqPred NomEq t1 t2 <- return (classifyPredType $ deconsPred ct)+          ]     tcPluginTrace "pres: final premises" (text $ show prems0)     tcPluginTrace "pres: final goals" (text $ show $ map snd wants)     case testIf prems (foldr ((:&&) . snd) PTrue wants) of@@ -310,27 +344,27 @@   nLeq <- tcLookupTyCon =<< lookupOrig gHC_TYPENATS (mkTcOcc "<=")   return     mempty-    { isEmpty = [emptyClsTyCon]-    , tyEq = [eqTyCon_]-    , tyEqWitness = [eqWitCon_]-    , isTrue = [isTrueCon_]-    , voids = [voidTyCon]-    , natMinus = [typeNatSubTyCon]-    , natPlus = [typeNatAddTyCon]-    , natTimes = [typeNatMulTyCon]-    , natExp = [typeNatExpTyCon]-    , falseData = [promotedFalseDataCon]-    , trueData = [promotedTrueDataCon]-    , natLeqBool = [typeNatLeqTyCon]-    , natLeq = [nLeq]-    , natCompare = [typeNatCmpTyCon]-    , orderingEQ = [promotedEQDataCon]-    , orderingLT = [promotedLTDataCon]-    , orderingGT = [promotedGTDataCon]-    }+      { isEmpty = [emptyClsTyCon]+      , tyEq = [eqTyCon_]+      , tyEqWitness = [eqWitCon_]+      , isTrue = [isTrueCon_]+      , voids = [voidTyCon]+      , natMinus = [typeNatSubTyCon]+      , natPlus = [typeNatAddTyCon]+      , natTimes = [typeNatMulTyCon]+      , natExp = [typeNatExpTyCon]+      , falseData = [promotedFalseDataCon]+      , trueData = [promotedTrueDataCon]+      , natLeqBool = [typeNatLeqTyCon]+      , natLeq = [nLeq]+      , natCompare = [typeNatCmpTyCon]+      , orderingEQ = [promotedEQDataCon]+      , orderingLT = [promotedLTDataCon]+      , orderingGT = [promotedGTDataCon]+      }  (<=>) :: Prop -> Prop -> Prop-p <=> q =  (p :&& q) :|| (Not p :&& Not q)+p <=> q = (p :&& q) :|| (Not p :&& Not q)  withEv :: Ct -> (EvTerm, Ct) withEv ct =@@ -340,34 +374,39 @@  orderingDic :: Given Translation => [(TyCon, Expr -> Expr -> Prop)] orderingDic =-  [(lt, (:<))  | lt <- orderingLT given ] ++-  [(eq, (:==)) | eq <- orderingEQ given ] ++-  [(gt, (:>))  | gt <- orderingGT given ]+  [(lt, (:<)) | lt <- orderingLT given]+  ++ [(eq, (:==)) | eq <- orderingEQ given]+    ++ [(gt, (:>)) | gt <- orderingGT given]  deconsPred :: Ct -> Type deconsPred = ctEvPred . ctEvidence  toPresburgerPred :: Given Translation => Type -> Machine Prop toPresburgerPred (TyConApp con [t1, t2])-  | con `elem` (natLeq given ++ natLeqBool given)-  = (:<=) <$> toPresburgerExp t1 <*> toPresburgerExp t2+  | con `elem` (natLeq given ++ natLeqBool given) =+    (:<=) <$> toPresburgerExp t1 <*> toPresburgerExp t2 toPresburgerPred ty   | Just (con, []) <- splitTyConApp_maybe ty-  , con `elem` trueData given = return PTrue+    , con `elem` trueData given =+    return PTrue   | Just (con, []) <- splitTyConApp_maybe ty-  , con `elem` falseData given = return PFalse-  | cls@(EqPred NomEq _ _) <- classifyPredType ty-  = toPresburgerPredTree cls+    , con `elem` falseData given =+    return PFalse+  | cls@(EqPred NomEq _ _) <- classifyPredType ty =+    toPresburgerPredTree cls   | isEqPred ty = toPresburgerPredTree $ classifyPredType ty   | Just (con, [l, r]) <- splitTyConApp_maybe ty -- l ~ r-  , con `elem` (tyEq given ++ tyEqBool given)-  = toPresburgerPredTree $ EqPred NomEq l r+    , con `elem` (tyEq given ++ tyEqBool given) =+    toPresburgerPredTree $ EqPred NomEq l r   | Just (con, [_k, l, r]) <- splitTyConApp_maybe ty -- l (:~: {k}) r-  , con `elem` tyEqWitness given = toPresburgerPredTree $ EqPred NomEq l r+    , con `elem` tyEqWitness given =+    toPresburgerPredTree $ EqPred NomEq l r   | Just (con, [l]) <- splitTyConApp_maybe ty -- Empty l => ...-  , con `elem` isEmpty given = Not <$> toPresburgerPred l+    , con `elem` isEmpty given =+    Not <$> toPresburgerPred l   | Just (con, [l]) <- splitTyConApp_maybe ty -- IsTrue l =>-  , con `elem` isTrue given = toPresburgerPred l+    , con `elem` isTrue given =+    toPresburgerPred l   | otherwise = parsePred given toPresburgerExp ty  splitTyConAppLastBin :: Type -> Maybe (TyCon, [Type])@@ -381,88 +420,92 @@ toPresburgerPredTree (EqPred NomEq p false) -- P ~ 'False <=> Not P ~ 'True   | maybe False (`elem` falseData given) $ tyConAppTyCon_maybe false =     Not <$> toPresburgerPredTree (EqPred NomEq p (mkTyConTy promotedTrueDataCon))-toPresburgerPredTree (EqPred NomEq p b)  -- (n :<=? m) ~ 'True+toPresburgerPredTree (EqPred NomEq p b) -- (n :<=? m) ~ 'True   | maybe False (`elem` trueData given) $ tyConAppTyCon_maybe b-  , Just (con, [t1, t2]) <- splitTyConAppLastBin p-  , con `elem` natLeqBool given = (:<=) <$> toPresburgerExp t1  <*> toPresburgerExp t2-toPresburgerPredTree (EqPred NomEq p q)  -- (p :: Bool) ~ (q :: Bool)-    | typeKind p `eqType` mkTyConTy promotedBoolTyCon = do-      lift $ lift $ tcPluginTrace "pres: EQBOOL:" $ ppr (p, q)-      (<=>) <$> toPresburgerPred p-            <*> toPresburgerPred q-toPresburgerPredTree (EqPred NomEq n m)  -- (n :: Nat) ~ (m :: Nat)+    , Just (con, [t1, t2]) <- splitTyConAppLastBin p+    , con `elem` natLeqBool given =+    (:<=) <$> toPresburgerExp t1 <*> toPresburgerExp t2+toPresburgerPredTree (EqPred NomEq p q) -- (p :: Bool) ~ (q :: Bool)+  | typeKind p `eqType` mkTyConTy promotedBoolTyCon = do+    lift $ lift $ tcPluginTrace "pres: EQBOOL:" $ ppr (p, q)+    (<=>) <$> toPresburgerPred p+      <*> toPresburgerPred q+toPresburgerPredTree (EqPred NomEq n m) -- (n :: Nat) ~ (m :: Nat)   | typeKind n `eqType` typeNatKind =     (:==) <$> toPresburgerExp n-          <*> toPresburgerExp m+      <*> toPresburgerExp m toPresburgerPredTree (EqPred _ t1 t2) -- CmpNat a b ~ CmpNat c d-  | Just (con,  lastTwo -> [a, b]) <- splitTyConAppLastBin t1-  , Just (con', lastTwo -> [c, d]) <- splitTyConAppLastBin t2-  , con `elem` natCompare given, con' `elem` natCompare given-  = (<=>) <$> ((:<) <$> toPresburgerExp a <*> toPresburgerExp b)-          <*> ((:<) <$> toPresburgerExp c <*> toPresburgerExp d)+  | Just (con, lastTwo -> [a, b]) <- splitTyConAppLastBin t1+    , Just (con', lastTwo -> [c, d]) <- splitTyConAppLastBin t2+    , con `elem` natCompare given+    , con' `elem` natCompare given =+    (<=>) <$> ((:<) <$> toPresburgerExp a <*> toPresburgerExp b)+      <*> ((:<) <$> toPresburgerExp c <*> toPresburgerExp d) toPresburgerPredTree (EqPred NomEq t1 t2) -- CmpNat a b ~ x   | Just (con, lastTwo -> [a, b]) <- splitTyConAppLastBin t1-  , con `elem` natCompare given-  , Just cmp <- tyConAppTyCon_maybe t2 =+    , con `elem` natCompare given+    , Just cmp <- tyConAppTyCon_maybe t2 =     MaybeT (return $ lookup cmp orderingDic)-       <*> toPresburgerExp a-       <*> toPresburgerExp b+      <*> toPresburgerExp a+      <*> toPresburgerExp b toPresburgerPredTree (EqPred NomEq t1 t2) -- x ~ CmpNat a b   | Just (con, lastTwo -> [a, b]) <- splitTyConAppLastBin t2-  , con `elem` natCompare given-  , Just cmp <- tyConAppTyCon_maybe t1 =+    , con `elem` natCompare given+    , Just cmp <- tyConAppTyCon_maybe t1 =     MaybeT (return $ lookup cmp orderingDic)-       <*> toPresburgerExp a-       <*> toPresburgerExp b+      <*> toPresburgerExp a+      <*> toPresburgerExp b toPresburgerPredTree (ClassPred con ts)   -- (n :: Nat) (<=| < | > | >= | == | /=) (m :: Nat)-  | let n = length ts, n >= 2-  , [t1, t2] <- drop (n - 2) ts-  , typeKind t1 `eqType` typeNatKind-  , typeKind t2 `eqType` typeNatKind =+  | let n = length ts+    , n >= 2+    , [t1, t2] <- drop (n - 2) ts+    , typeKind t1 `eqType` typeNatKind+    , typeKind t2 `eqType` typeNatKind =     let p = lookup (classTyCon con) binPropDic-    in MaybeT (return p) <*> toPresburgerExp t1 <*> toPresburgerExp t2+     in MaybeT (return p) <*> toPresburgerExp t1 <*> toPresburgerExp t2 toPresburgerPredTree _ = mzero  binPropDic :: Given Translation => [(TyCon, Expr -> Expr -> Prop)] binPropDic =-  [ (n, (:<)) | n <- natLt given ++ natLtBool given ] ++-  [ (n, (:>)) | n <- natGt given ++ natGtBool given ] ++-  [ (n, (:<=)) | n <- natLeq given ++ natLeqBool given ] ++-  [ (n, (:>=)) | n <- natGeq given ++ natGeqBool given ] ++-  [ (n, (:==)) | n <- tyEq given ++ tyEqBool given ] ++-  [ (n, (:/=)) | n <- tyNeqBool given ]+  [(n, (:<)) | n <- natLt given ++ natLtBool given]+  ++ [(n, (:>)) | n <- natGt given ++ natGtBool given]+    ++ [(n, (:<=)) | n <- natLeq given ++ natLeqBool given]+    ++ [(n, (:>=)) | n <- natGeq given ++ natGeqBool given]+    ++ [(n, (:==)) | n <- tyEq given ++ tyEqBool given]+    ++ [(n, (:/=)) | n <- tyNeqBool given]  toPresburgerExp :: Given Translation => Type -> Machine Expr toPresburgerExp ty = case ty of-  TyVarTy t          -> return $ Var $ toName $ getKey $ getUnique t+  TyVarTy t -> return $ Var $ toName $ getKey $ getUnique t   t@(TyConApp tc ts) -> body tc ts <|> Var . toName . getKey . getUnique <$> toVar t   LitTy (NumTyLit n) -> return (K n)-  LitTy _            -> mzero-  t                  ->-        parseExpr given ty-    <|> Var . toName . getKey .getUnique <$> toVar t+  LitTy _ -> mzero+  t ->+    parseExpr given ty+      <|> Var . toName . getKey . getUnique <$> toVar t   where     body tc ts =       let step con op-            | tc == con, [tl, tr] <- lastTwo ts =+            | tc == con+              , [tl, tr] <- lastTwo ts =               op <$> toPresburgerExp tl <*> toPresburgerExp tr             | otherwise = mzero-      in case ts of-        [tl, tr] | tc `elem` natTimes given ->-          case (simpleExp tl, simpleExp tr) of-            (LitTy (NumTyLit n), LitTy (NumTyLit m)) -> return $ K $ n * m-            (LitTy (NumTyLit n), x) -> (:*) <$> pure n <*> toPresburgerExp x-            (x, LitTy (NumTyLit n)) -> (:*) <$> pure n <*> toPresburgerExp x-            _ -> mzero-        _ ->  asum-           $  [ step con (:+)-              | con <- natPlus given-              ] ++-              [ step con (:-)-              | con <- natMinus given-              ]-+       in case ts of+            [tl, tr] | tc `elem` natTimes given ->+              case (simpleExp tl, simpleExp tr) of+                (LitTy (NumTyLit n), LitTy (NumTyLit m)) -> return $ K $ n * m+                (LitTy (NumTyLit n), x) -> (:*) <$> pure n <*> toPresburgerExp x+                (x, LitTy (NumTyLit n)) -> (:*) <$> pure n <*> toPresburgerExp x+                _ -> mzero+            _ ->+              asum $+                [ step con (:+)+                | con <- natPlus given+                ]+                  ++ [ step con (:-)+                     | con <- natMinus given+                     ]  -- simplTypeCmp :: Type -> Type @@ -477,20 +520,23 @@ simpleExp (FunTy t1 t2) = FunTy (simpleExp t1) (simpleExp t2) #endif simpleExp (ForAllTy t1 t2) = ForAllTy t1 (simpleExp t2)-simpleExp (TyConApp tc (lastTwo -> ts)) = fromMaybe (TyConApp tc (map simpleExp ts)) $-  asum (map simpler-        $ [(c, (+)) | c <- natPlus given] ++-          [(c, (-)) | c <- natMinus given] ++-          [(c, (*)) | c <- natTimes given] ++-          [(c, (^)) | c <- natExp given]+simpleExp (TyConApp tc (lastTwo -> ts)) =+  fromMaybe (TyConApp tc (map simpleExp ts)) $+    asum+      ( map simpler $+          [(c, (+)) | c <- natPlus given]+          ++ [(c, (-)) | c <- natMinus given]+            ++ [(c, (*)) | c <- natTimes given]+            ++ [(c, (^)) | c <- natExp given]       )   where     simpler (con, op)-      | con == tc, [tl, tr] <- map simpleExp ts =+      | con == tc+        , [tl, tr] <- map simpleExp ts =         Just $-        case (tl, tr) of-          (LitTy (NumTyLit n), LitTy (NumTyLit m)) -> LitTy (NumTyLit (op n m))-          _ -> TyConApp con [tl, tr]+          case (tl, tr) of+            (LitTy (NumTyLit n), LitTy (NumTyLit m)) -> LitTy (NumTyLit (op n m))+            _ -> TyConApp con [tl, tr]       | otherwise = Nothing simpleExp t = t @@ -506,9 +552,10 @@   return ma  toVar :: Type -> Machine TyVar-toVar ty = gets (M.lookup (TypeEq ty)) >>= \case-  Just v -> return v-  Nothing -> do-    v <- lift $ lift $ newFlexiTyVar $ typeKind ty-    modify $ M.insert (TypeEq ty) v-    return v+toVar ty =+  gets (M.lookup (TypeEq ty)) >>= \case+    Just v -> return v+    Nothing -> do+      v <- lift $ lift $ newFlexiTyVar $ typeKind ty+      modify $ M.insert (TypeEq ty) v+      return v
+ test/ErrorsNoPlugin.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# OPTIONS_GHC -fdefer-type-errors #-}++module ErrorsNoPlugin where++import Shared++zipMVec :: Vec n a -> Vec n b -> Vec n (a, b)+zipMVec Nil Nil = Nil+zipMVec zs@(a :- as) (b :- bs) = (a, b) :- zipMVec zs bs++spin :: Vec n a -> Vec n a -> ()+spin _ _ = ()++unSpin :: Vec n a -> ()+unSpin Nil = ()+unSpin zs@(_ :- ws) = spin zs ws
+ test/ErrorsWithPlugin.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# OPTIONS_GHC -fdefer-type-errors #-}+{-# OPTIONS_GHC -fplugin GHC.TypeLits.Presburger #-}++module ErrorsWithPlugin where++import Shared++zipMVec :: Vec n a -> Vec n b -> Vec n (a, b)+zipMVec Nil Nil = Nil+zipMVec zs@(a :- as) (b :- bs) = (a, b) :- zipMVec zs bs++spin :: Vec n a -> Vec n a -> ()+spin _ _ = ()++unSpin :: Vec n a -> ()+unSpin Nil = ()+unSpin zs@(_ :- ws) = spin zs ws
+ test/GHC/TypeLits/PresburgerSpec.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE OverloadedStrings #-}++module GHC.TypeLits.PresburgerSpec where++import Control.Exception (evaluate, try)+import Control.Exception.Base (TypeError (TypeError))+import Control.Monad (void)+import qualified Data.Text as T+import qualified ErrorsNoPlugin as NoPlugin+import qualified ErrorsWithPlugin as Plugin+import Shared+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertFailure, testCase)++test_recursiveContradiction :: TestTree+test_recursiveContradiction =+  testGroup+    "n ~ n + 1 in recursive call should be rejected as type error"+    [ testCase "Without plugin" $ do+        eith <- try $ void (evaluate $ NoPlugin.zipMVec (True :- Nil) (() :- Nil))+        case eith of+          Left (TypeError msg)+            | "Could not deduce: (n GHC.TypeNats.+ 1) ~ n"+                `T.isInfixOf` T.pack msg ->+              pure ()+          _ -> assertFailure $ "TypeError with mismatch expected, but got: " <> show eith+    , testCase "With plugin" $ do+        eith <- try $ void (evaluate $ Plugin.zipMVec (True :- Nil) (() :- Nil))+        case eith of+          Left (TypeError msg)+            | "Could not deduce: (n GHC.TypeNats.+ 1) ~ n"+                `T.isInfixOf` T.pack msg ->+              pure ()+          _ -> assertFailure $ "TypeError with mismatch expected, but got: " <> show eith+    ]++test_nonrecursiveContradiction :: TestTree+test_nonrecursiveContradiction =+  testGroup+    "n ~ n + 1 in non-recursive call should be rejected as type error"+    [ testCase "Without plugin" $ do+        eith <- try $ void (evaluate $ NoPlugin.unSpin (True :- Nil))+        case eith of+          Left (TypeError msg)+            | "Could not deduce: n1 ~ n"+                `T.isInfixOf` T.pack msg ->+              pure ()+          _ -> assertFailure $ "TypeError with mismatch expected, but got: " <> show eith+    , testCase "With plugin" $ do+        eith <- try $ void (evaluate $ Plugin.unSpin (True :- Nil))+        case eith of+          Left (TypeError msg)+            | "Could not deduce: n1 ~ n"+                `T.isInfixOf` T.pack msg ->+              pure ()+          _ -> assertFailure $ "TypeError with mismatch expected, but got: " <> show eith+    ]
+ test/Shared.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE TypeOperators #-}++module Shared (Vec (..)) where++import GHC.TypeNats (Nat, type (+))++data Vec (n :: Nat) a where+  Nil :: Vec 0 a+  (:-) :: a -> Vec n a -> Vec (n + 1) a++infixr 9 :-
+ test/test.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF tasty-discover #-}