diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,10 @@
 .ghc.environment.*
 
 # GHC
+dist-boot
 dist-install
 GNUmakefile
 ghc.mk
+
+# MHS
+dist-mcabal
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
--- a/.travis.yml
+++ /dev/null
@@ -1,204 +0,0 @@
-# This Travis job script has been generated by a script via
-#
-#   haskell-ci '--output=.travis.yml' '--config=cabal.haskell-ci' 'cabal.project'
-#
-# For more information, see https://github.com/haskell-CI/haskell-ci
-#
-# version: 0.9.20191213
-#
-version: ~> 1.0
-language: c
-os: linux
-dist: xenial
-git:
-  # whether to recursively clone submodules
-  submodules: false
-notifications:
-  irc:
-    channels:
-      - irc.freenode.org#haskell-lens
-    skip_join: true
-    template:
-      - "\"\\x0313exceptions\\x03/\\x0306%{branch}\\x03 \\x0314%{commit}\\x03 %{build_url} %{message}\""
-cache:
-  directories:
-    - $HOME/.cabal/packages
-    - $HOME/.cabal/store
-    - $HOME/.hlint
-before_cache:
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log
-  # remove files that are regenerated by 'cabal update'
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar
-  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx
-  - rm -rfv $CABALHOME/packages/head.hackage
-jobs:
-  include:
-    - compiler: ghc-8.10.1
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.10.1","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-8.8.1
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.8.1","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-8.6.5
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.6.5","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-8.4.4
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.4.4","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-8.2.2
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.2.2","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-8.0.2
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.0.2","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.10.3
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.10.3","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.8.4
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.8.4","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.6.3
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.6.3","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.4.2
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.4.2","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.2.2
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.2.2","cabal-install-3.0"]}}
-      os: linux
-    - compiler: ghc-7.0.4
-      addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.0.4","cabal-install-3.0"]}}
-      os: linux
-  allow_failures:
-    - compiler: ghc-7.0.4
-    - compiler: ghc-7.2.2
-    - compiler: ghc-8.10.1
-before_install:
-  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')
-  - WITHCOMPILER="-w $HC"
-  - HADDOCK=$(echo "/opt/$CC/bin/haddock" | sed 's/-/\//')
-  - HCPKG="$HC-pkg"
-  - unset CC
-  - CABAL=/opt/ghc/bin/cabal
-  - CABALHOME=$HOME/.cabal
-  - export PATH="$CABALHOME/bin:$PATH"
-  - TOP=$(pwd)
-  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
-  - echo $HCNUMVER
-  - CABAL="$CABAL -vnormal+nowrap+markoutput"
-  - set -o pipefail
-  - |
-    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk
-    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk
-    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk
-    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk
-    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk
-    echo '  if (state == "cabal") {'                                       >> .colorful.awk
-    echo '    print blue($0)'                                              >> .colorful.awk
-    echo '  } else {'                                                      >> .colorful.awk
-    echo '    print $0'                                                    >> .colorful.awk
-    echo '  }'                                                             >> .colorful.awk
-    echo '}'                                                               >> .colorful.awk
-  - cat .colorful.awk
-  - |
-    color_cabal_output () {
-      awk -f $TOP/.colorful.awk
-    }
-  - echo text | color_cabal_output
-install:
-  - ${CABAL} --version
-  - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
-  - TEST=--enable-tests
-  - BENCH=--enable-benchmarks
-  - HEADHACKAGE=false
-  - if [ $HCNUMVER -ge 81000 ] ; then HEADHACKAGE=true ; fi
-  - rm -f $CABALHOME/config
-  - |
-    echo "verbose: normal +nowrap +markoutput"                                  >> $CABALHOME/config
-    echo "remote-build-reporting: anonymous"                                    >> $CABALHOME/config
-    echo "write-ghc-environment-files: always"                                  >> $CABALHOME/config
-    echo "remote-repo-cache: $CABALHOME/packages"                               >> $CABALHOME/config
-    echo "logs-dir:          $CABALHOME/logs"                                   >> $CABALHOME/config
-    echo "world-file:        $CABALHOME/world"                                  >> $CABALHOME/config
-    echo "extra-prog-path:   $CABALHOME/bin"                                    >> $CABALHOME/config
-    echo "symlink-bindir:    $CABALHOME/bin"                                    >> $CABALHOME/config
-    echo "installdir:        $CABALHOME/bin"                                    >> $CABALHOME/config
-    echo "build-summary:     $CABALHOME/logs/build.log"                         >> $CABALHOME/config
-    echo "store-dir:         $CABALHOME/store"                                  >> $CABALHOME/config
-    echo "install-dirs user"                                                    >> $CABALHOME/config
-    echo "  prefix: $CABALHOME"                                                 >> $CABALHOME/config
-    echo "repository hackage.haskell.org"                                       >> $CABALHOME/config
-    echo "  url: http://hackage.haskell.org/"                                   >> $CABALHOME/config
-    echo "  secure: True"                                                       >> $CABALHOME/config
-    echo "  key-threshold: 3"                                                   >> $CABALHOME/config
-    echo "  root-keys:"                                                         >> $CABALHOME/config
-    echo "    fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0" >> $CABALHOME/config
-    echo "    1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42" >> $CABALHOME/config
-    echo "    2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3" >> $CABALHOME/config
-    echo "    0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d" >> $CABALHOME/config
-    echo "    51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921" >> $CABALHOME/config
-  - |
-    if $HEADHACKAGE; then
-    echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config
-    echo "repository head.hackage.ghc.haskell.org"                                        >> $CABALHOME/config
-    echo "   url: https://ghc.gitlab.haskell.org/head.hackage/"                           >> $CABALHOME/config
-    echo "   secure: True"                                                                >> $CABALHOME/config
-    echo "   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d" >> $CABALHOME/config
-    echo "              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329" >> $CABALHOME/config
-    echo "              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89" >> $CABALHOME/config
-    echo "   key-threshold: 3"                                                            >> $CABALHOME/config
-    fi
-  - |
-    echo "program-default-options"                >> $CABALHOME/config
-    echo "  ghc-options: $GHCJOBS +RTS -M6G -RTS" >> $CABALHOME/config
-  - cat $CABALHOME/config
-  - rm -fv cabal.project cabal.project.local cabal.project.freeze
-  - travis_retry ${CABAL} v2-update -v
-  # Generate cabal.project
-  - rm -rf cabal.project cabal.project.local cabal.project.freeze
-  - touch cabal.project
-  - |
-    echo "packages: ." >> cabal.project
-  - |
-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(exceptions)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
-  - cat cabal.project || true
-  - cat cabal.project.local || true
-  - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi
-  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output
-  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
-  - rm  cabal.project.freeze
-  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output
-script:
-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
-  # Packaging...
-  - ${CABAL} v2-sdist all | color_cabal_output
-  # Unpacking...
-  - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
-  - cd ${DISTDIR} || false
-  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;
-  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;
-  - PKGDIR_exceptions="$(find . -maxdepth 1 -type d -regex '.*/exceptions-[0-9.]*')"
-  # Generate cabal.project
-  - rm -rf cabal.project cabal.project.local cabal.project.freeze
-  - touch cabal.project
-  - |
-    echo "packages: ${PKGDIR_exceptions}" >> cabal.project
-  - |
-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(exceptions)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
-  - cat cabal.project || true
-  - cat cabal.project.local || true
-  # Building with tests and benchmarks...
-  # build & run tests, build benchmarks
-  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output
-  # Testing...
-  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output
-  # cabal check...
-  - (cd ${PKGDIR_exceptions} && ${CABAL} -vnormal check)
-  # haddock...
-  - ${CABAL} v2-haddock $WITHCOMPILER --with-haddock $HADDOCK ${TEST} ${BENCH} all | color_cabal_output
-
-# REGENDATA ("0.9.20191213",["--output=.travis.yml","--config=cabal.haskell-ci","cabal.project"])
-# EOF
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,55 @@
+0.10.12 [2026.01.10]
+--------------------
+* Add `Monad{Throw,Catch,Mask}` instances for `AccumT` when building with
+  `transformers-0.5.6` or later.
+* Remove unused `template-haskell` dependency in the test suite.
+
+0.10.11 [2025.10.13]
+--------------------
+* Add a `rethrowM` method to the `MonadThrow` class and a `catchNoPropagate`
+  method to the `MonadCatch` class, which are available when building with
+  `base-4.21` (GHC 9.12) or later. These are like `throwM` and `catch`,
+  respectively (and use them as their default implementations), but these
+  methods do not add new backtraces (for `rethrowM`) or annotate the handler
+  with the exception that was caught (for `catchNoPropagate`).
+* Support building with MicroHs.
+
+0.10.10 [2025.06.17]
+--------------------
+* Replace `test-framework` with `tasty` in the test suite.
+
+0.10.9 [2024.10.31]
+-------------------
+* Drop support for pre-8.0 versions of GHC.
+
+0.10.8 [2024.04.20]
+-------------------
+* Allow building with `template-haskell-2.22.*`.
+* Make the test suite build with GHC 9.4 and `mtl-2.3.1`.
+
+0.10.7 [2022.12.04]
+-------------------
+* On pre-8.0 GHCs, drop the `call-stack` dependency. This dependency was
+  introduced in `exceptions-0.10.6`, but it induced breakage in libraries
+  that derived instances of `MonadThrow`, `MonadCatch`, or `MonadMask` for
+  newtypes without first enabling `ConstraintKinds` and `FlexibleContexts`.
+  (Later versions of GHC do not require these language extensions for derived
+  instances, so only old GHCs were affected.) To avoid breakage, `exceptions`
+  no longer uses `HasCallStack` constraints on pre-8.0 versions of GHC.
+
+  Note that `exceptions` still uses `HasCallStack` constraints on GHC 8.0 and
+  later, and as a result, these versions of GHC are unaffected by this change.
+
+0.10.6 [2022.11.30]
+-------------------
+* The class methods and functions in `Control.Monad.Catch` now have
+  `HasCallStack` constraints.
+* Drop support for GHC 7.0 and 7.2.
+
+0.10.5 [2022.05.07]
+-------------------
+* Allow building with `transformers-0.6.*` and `mtl-2.3.*`.
+
 0.10.4 [2019.12.26]
 -------------------
 * Allow building with `template-haskell-2.16.*`.
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -1,7 +1,7 @@
 exceptions
 ==========
 
-[![Hackage](https://img.shields.io/hackage/v/exceptions.svg)](https://hackage.haskell.org/package/exceptions) [![Build Status](https://secure.travis-ci.org/ekmett/exceptions.png?branch=master)](http://travis-ci.org/ekmett/exceptions)
+[![Hackage](https://img.shields.io/hackage/v/exceptions.svg)](https://hackage.haskell.org/package/exceptions) [![Build Status](https://github.com/ekmett/exceptions/workflows/Haskell-CI/badge.svg)](https://github.com/ekmett/exceptions/actions?query=workflow%3AHaskell-CI)
 
 This package provides (optionally pure) extensible exceptions that are compatible with the monad transformer library.
 
diff --git a/exceptions.cabal b/exceptions.cabal
--- a/exceptions.cabal
+++ b/exceptions.cabal
@@ -1,7 +1,7 @@
 name:          exceptions
 category:      Control, Exceptions, Monad
-version:       0.10.4
-cabal-version: >= 1.8
+version:       0.10.12
+cabal-version: >= 1.10
 license:       BSD3
 license-file:  LICENSE
 author:        Edward A. Kmett
@@ -12,86 +12,67 @@
 copyright:     Copyright (C) 2013-2015 Edward A. Kmett
                Copyright (C) 2012 Google Inc.
 build-type:    Simple
-tested-with:   GHC == 7.0.4
-             , GHC == 7.2.2
-             , GHC == 7.4.2
-             , GHC == 7.6.3
-             , GHC == 7.8.4
-             , GHC == 7.10.3
-             , GHC == 8.0.2
+tested-with:   GHC == 8.0.2
              , GHC == 8.2.2
              , GHC == 8.4.4
              , GHC == 8.6.5
-             , GHC == 8.8.1
-             , GHC == 8.10.1
+             , GHC == 8.8.4
+             , GHC == 8.10.7
+             , GHC == 9.0.2
+             , GHC == 9.2.8
+             , GHC == 9.4.8
+             , GHC == 9.6.7
+             , GHC == 9.8.4
+             , GHC == 9.10.3
+             , GHC == 9.12.2
+             , GHC == 9.14.1
 synopsis:      Extensible optionally-pure exceptions
 description:   Extensible optionally-pure exceptions.
 
 extra-source-files:
-  .travis.yml
   .ghci
   .gitignore
   .vim.custom
-  travis/cabal-apt-install
-  travis/config
   AUTHORS.markdown
   README.markdown
   CHANGELOG.markdown
 
 source-repository head
   type: git
-  location: git://github.com/ekmett/exceptions.git
-
-flag transformers-0-4
-  description: Use @transformers-0.4@ or later.
-  default:     True
+  location: https://github.com/ekmett/exceptions.git
 
 library
   build-depends:
-    base                       >= 4.3      && < 5,
+    base                       >= 4.9      && < 5,
+    mtl                        >= 2.2      && < 2.4,
     stm                        >= 2.2      && < 3,
-    template-haskell           >= 2.2      && < 2.17,
-    mtl                        >= 2.0      && < 2.3
-
-  if !impl(ghc >= 8.0)
-    build-depends: fail        == 4.9.*
-
-  if flag(transformers-0-4)
-    build-depends:
-      transformers             >= 0.4      && < 0.6
-  else
+    transformers               >= 0.5.2.0  && < 0.7
+  if impl(ghc)
     build-depends:
-      transformers             >= 0.2      && < 0.4,
-      transformers-compat      >= 0.3      && < 0.7
+      template-haskell         >= 2.11     && < 2.25
 
   exposed-modules:
     Control.Monad.Catch
     Control.Monad.Catch.Pure
 
-  ghc-options: -Wall -fwarn-tabs -O2
+  ghc-options: -Wall -Wtabs -O2
   hs-source-dirs: src
+  default-language: Haskell2010
 
 test-suite exceptions-tests
   main-is: Tests.hs
   other-modules: Control.Monad.Catch.Tests
   hs-source-dirs: tests
-  ghc-options: -Wall -fwarn-tabs
+  ghc-options: -Wall -Wtabs
+  default-language: Haskell2010
   type: exitcode-stdio-1.0
   build-depends:
     base,
     exceptions,
+    mtl,
     stm,
-    template-haskell,
-    mtl                        >= 2.0,
-    test-framework             >= 0.8      && < 0.9,
-    test-framework-hunit       >= 0.3      && < 0.4,
-    test-framework-quickcheck2 >= 0.3      && < 0.4,
-    QuickCheck                 >= 2.5      && < 2.14
-
-  if flag(transformers-0-4)
-    build-depends:
-      transformers             >= 0.4      && < 0.6
-  else
-    build-depends:
-      transformers             >= 0.2      && < 0.4,
-      transformers-compat      >= 0.3      && < 0.7
+    transformers     >= 0.5.2.0 && < 0.7,
+    tasty            >= 1.4     && < 1.6,
+    tasty-hunit      >= 0.10    && < 0.11,
+    tasty-quickcheck >= 0.10    && < 0.12,
+    QuickCheck       >= 2.5     && < 2.18
diff --git a/src/Control/Monad/Catch.hs b/src/Control/Monad/Catch.hs
--- a/src/Control/Monad/Catch.hs
+++ b/src/Control/Monad/Catch.hs
@@ -1,25 +1,19 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE TypeFamilies #-}
-
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE Trustworthy #-}
-#endif
-
-#ifndef MIN_VERSION_transformers
-#define MIN_VERSION_transformers(x,y,z) 1
-#endif
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
 
-#ifndef MIN_VERSION_mtl
-#define MIN_VERSION_mtl(x,y,z) 1
+#if !MIN_VERSION_transformers(0,6,0)
+{-# OPTIONS_GHC -Wno-deprecations #-}
 #endif
-
-{-# OPTIONS_GHC -fno-warn-deprecations #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012
@@ -36,7 +30,7 @@
 -- with them, though doesn't mimic the module structure or offer the complete
 -- range of features in those packages.
 --
--- This is very similar to 'ErrorT' and 'MonadError', but based on features of
+-- This is very similar to 'ExceptT' and 'MonadError', but based on features of
 -- "Control.Exception". In particular, it handles the complex case of
 -- asynchronous exceptions by including 'mask' in the typeclass. Note that the
 -- extensible exceptions feature relies on the RankNTypes language extension.
@@ -79,6 +73,7 @@
 
 import Control.Exception (Exception(..), SomeException(..))
 import qualified Control.Exception as ControlException
+import Control.Monad (liftM)
 import qualified Control.Monad.STM as STM
 import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS
 import qualified Control.Monad.Trans.RWS.Strict as StrictRWS
@@ -87,35 +82,31 @@
 import qualified Control.Monad.Trans.Writer.Lazy as LazyW
 import qualified Control.Monad.Trans.Writer.Strict as StrictW
 import Control.Monad.ST (ST)
+import Control.Monad.ST.Unsafe (unsafeIOToST)
 import Control.Monad.STM (STM)
-import Control.Monad.Trans.List (ListT(..), runListT)
+import Control.Monad.Trans.Class (MonadTrans(..))
 import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
-import Control.Monad.Trans.Error (ErrorT(..), Error, runErrorT)
 import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
 import Control.Monad.Trans.Cont (ContT)
 import Control.Monad.Trans.Identity
-import Control.Monad.Reader as Reader
+import Control.Monad.Trans.Reader (ReaderT(..), runReaderT)
 
-import Language.Haskell.TH.Syntax (Q)
+import GHC.Stack (HasCallStack, withFrozenCallStack)
 
-#if MIN_VERSION_base(4,4,0)
-import Control.Monad.ST.Unsafe (unsafeIOToST)
+#if defined(__MHS__)
+import Prelude hiding(foldr)
+import Data.Foldable
 #else
-import Control.Monad.ST (unsafeIOToST)
+import Language.Haskell.TH.Syntax (Q)
 #endif
 
-#if __GLASGOW_HASKELL__ < 706
-import Prelude hiding (catch, foldr)
-import Data.Foldable
-import Data.Monoid
-#elif __GLASGOW_HASKELL__ < 710
-import Prelude hiding (foldr)
-import Data.Foldable
-import Data.Monoid
+#if MIN_VERSION_transformers(0,5,6)
+import Control.Monad.Trans.Accum (AccumT (..), runAccumT, evalAccumT)
 #endif
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
+#if !MIN_VERSION_transformers(0,6,0)
+import Control.Monad.Trans.Error (ErrorT(..), Error, runErrorT)
+import Control.Monad.Trans.List (ListT(..), runListT)
 #endif
 
 ------------------------------------------------------------------------------
@@ -139,8 +130,20 @@
   -- Should satisfy the law:
   --
   -- > throwM e >> f = throwM e
-  throwM :: Exception e => e -> m a
+  throwM :: (HasCallStack, Exception e) => e -> m a
 
+#if MIN_VERSION_base(4,21,0)
+  -- | A utility to use when rethrowing exceptions, no new backtrace will be
+  -- attached when rethrowing an exception but you must supply the existing
+  -- context.
+  --
+  -- It is a generalization of "Control.Exception"'s
+  -- 'ControlException.rethrowIO' and is only defined using @base-4.21@ (GHC
+  -- 9.12) or later.
+  rethrowM :: Exception e => ControlException.ExceptionWithContext e -> m a
+  rethrowM = throwM
+#endif
+
 -- | A class for monads which allow exceptions to be caught, in particular
 -- exceptions which were thrown by 'throwM'.
 --
@@ -159,7 +162,21 @@
   -- action. Note that type of the type of the argument to the handler will
   -- constrain which exceptions are caught. See "Control.Exception"'s
   -- 'ControlException.catch'.
-  catch :: Exception e => m a -> (e -> m a) -> m a
+  catch :: (HasCallStack, Exception e) => m a -> (e -> m a) -> m a
+#if MIN_VERSION_base(4,21,0)
+  -- | A variant of 'catch' which doesn't annotate the handler with the exception
+  -- which was caught. This function should be used when you are implementing
+  -- your own error handling functions which may rethrow the exceptions.
+  --
+  -- In the case where you rethrow an exception without modifying it, you
+  -- should rethrow the exception with the old exception context.
+  --
+  -- It is a generalization of "Control.Exception"'s
+  -- 'ControlException.catchNoPropagate' and is only defined using @base-4.21@
+  -- (GHC 9.12) or later.
+  catchNoPropagate :: Exception e => m a -> (ControlException.ExceptionWithContext e -> m a) -> m a
+  catchNoPropagate = catch
+#endif
 
 -- | A class for monads which provide for the ability to account for
 -- all possible exit points from a computation, and to mask
@@ -183,7 +200,7 @@
 -- error from the same layer, instances should ensure that the error from @g@
 -- wins.
 --
--- Effects other than throwing an error are also overriden by the deeper layers.
+-- Effects other than throwing an error are also overridden by the deeper layers.
 -- For example, @StateT s Maybe a@ represents a value of type @s -> Maybe (a,
 -- s)@, so if an error thrown from @f@ causes this function to return @Nothing@,
 -- any changes to the state which @f@ also performed will be erased. As a
@@ -200,7 +217,7 @@
   -- | Runs an action with asynchronous exceptions disabled. The action is
   -- provided a method for restoring the async. environment to what it was
   -- at the 'mask' call. See "Control.Exception"'s 'ControlException.mask'.
-  mask :: ((forall a. m a -> m a) -> m b) -> m b
+  mask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b
 
   -- | Like 'mask', but the masked computation is not interruptible (see
   -- "Control.Exception"'s 'ControlException.uninterruptibleMask'. WARNING:
@@ -208,7 +225,7 @@
   -- AND you can guarantee the interruptible operation will only block for a
   -- short period of time. Otherwise you render the program/thread unresponsive
   -- and/or unkillable.
-  uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b
+  uninterruptibleMask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b
 
   -- | A generalized version of 'bracket' which uses 'ExitCase' to distinguish
   -- the different exit cases, and returns the values of both the 'use' and
@@ -225,27 +242,25 @@
   -- library. Previously, implementation of functions like 'bracket'
   -- and 'finally' in this module were based on the 'mask' and
   -- 'uninterruptibleMask' functions only, disallowing some classes of
-  -- tranformers from having @MonadMask@ instances (notably
+  -- transformers from having @MonadMask@ instances (notably
   -- multi-exit-point transformers like 'ExceptT'). If you are a
   -- library author, you'll now need to provide an implementation for
   -- this method. The @StateT@ implementation demonstrates most of the
   -- subtleties:
   --
-  -- @
-  -- generalBracket acquire release use = StateT $ \s0 -> do
-  --   ((b, _s2), (c, s3)) <- generalBracket
-  --     (runStateT acquire s0)
-  --     (\(resource, s1) exitCase -> case exitCase of
-  --       ExitCaseSuccess (b, s2) -> runStateT (release resource (ExitCaseSuccess b)) s2
-  --
-  --       -- In the two other cases, the base monad overrides @use@'s state
-  --       -- changes and the state reverts to @s1@.
-  --       ExitCaseException e     -> runStateT (release resource (ExitCaseException e)) s1
-  --       ExitCaseAbort           -> runStateT (release resource ExitCaseAbort) s1
-  --     )
-  --     (\(resource, s1) -> runStateT (use resource) s1)
-  --   return ((b, c), s3)
-  -- @
+  -- > generalBracket acquire release use = StateT $ \s0 -> do
+  -- >   ((b, _s2), (c, s3)) <- generalBracket
+  -- >     (runStateT acquire s0)
+  -- >     (\(resource, s1) exitCase -> case exitCase of
+  -- >       ExitCaseSuccess (b, s2) -> runStateT (release resource (ExitCaseSuccess b)) s2
+  -- >
+  -- >       -- In the two other cases, the base monad overrides `use`'s state
+  -- >       -- changes and the state reverts to `s1`.
+  -- >       ExitCaseException e     -> runStateT (release resource (ExitCaseException e)) s1
+  -- >       ExitCaseAbort           -> runStateT (release resource ExitCaseAbort) s1
+  -- >     )
+  -- >     (\(resource, s1) -> runStateT (use resource) s1)
+  -- >   return ((b, c), s3)
   --
   -- The @StateT s m@ implementation of @generalBracket@ delegates to the @m@
   -- implementation of @generalBracket@. The @acquire@, @use@, and @release@
@@ -279,29 +294,28 @@
   -- take priority. Here is an implementation for @ExceptT@ which demonstrates
   -- how to do this.
   --
-  -- @
-  -- generalBracket acquire release use = ExceptT $ do
-  --   (eb, ec) <- generalBracket
-  --     (runExceptT acquire)
-  --     (\eresource exitCase -> case eresource of
-  --       Left e -> return (Left e) -- nothing to release, acquire didn't succeed
-  --       Right resource -> case exitCase of
-  --         ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))
-  --         ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))
-  --         _                         -> runExceptT (release resource ExitCaseAbort))
-  --     (either (return . Left) (runExceptT . use))
-  --   return $ do
-  --     -- The order in which we perform those two 'Either' effects determines
-  --     -- which error will win if they are both 'Left's. We want the error from
-  --     -- 'release' to win.
-  --     c <- ec
-  --     b <- eb
-  --     return (b, c)
-  -- @
+  -- > generalBracket acquire release use = ExceptT $ do
+  -- >   (eb, ec) <- generalBracket
+  -- >     (runExceptT acquire)
+  -- >     (\eresource exitCase -> case eresource of
+  -- >       Left e -> return (Left e) -- nothing to release, `acquire` didn't succeed
+  -- >       Right resource -> case exitCase of
+  -- >         ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))
+  -- >         ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))
+  -- >         _                         -> runExceptT (release resource ExitCaseAbort))
+  -- >     (either (return . Left) (runExceptT . use))
+  -- >   return $ do
+  -- >     -- The order in which we perform those two `Either` effects determines
+  -- >     -- which error will win if they are both `Left`s. We want the error from
+  -- >     -- `release` to win.
+  -- >     c <- ec
+  -- >     b <- eb
+  -- >     return (b, c)
   --
   -- @since 0.9.0
   generalBracket
-    :: m a
+    :: HasCallStack
+    => m a
     -- ^ acquire some resource
     -> (a -> ExitCase b -> m c)
     -- ^ release the resource, observing the outcome of the inner action
@@ -324,26 +338,51 @@
   throwM _ = []
 instance MonadThrow Maybe where
   throwM _ = Nothing
+#if !defined(__MHS__)
 instance MonadThrow Q where
   throwM = fail . show
+#endif
 
 instance MonadThrow IO where
   throwM = ControlException.throwIO
+#if MIN_VERSION_base(4,21,0)
+  rethrowM = ControlException.rethrowIO
+#endif
 instance MonadCatch IO where
   catch = ControlException.catch
+#if MIN_VERSION_base(4,21,0)
+  catchNoPropagate = ControlException.catchNoPropagate
+#endif
 instance MonadMask IO where
   mask = ControlException.mask
   uninterruptibleMask = ControlException.uninterruptibleMask
+
+
+#if MIN_VERSION_base(4,21,0)
   generalBracket acquire release use = mask $ \unmasked -> do
     resource <- acquire
+
+    b <- unmasked (use resource) `catchNoPropagate` \e -> do
+      _ <- release resource (ExitCaseException $ ControlException.toException e)
+      rethrowM @IO @SomeException e
+    c <- release resource (ExitCaseSuccess b)
+    return (b, c)
+#else
+  generalBracket acquire release use = mask $ \unmasked -> do
+    resource <- acquire
+
     b <- unmasked (use resource) `catch` \e -> do
       _ <- release resource (ExitCaseException e)
       throwM e
     c <- release resource (ExitCaseSuccess b)
     return (b, c)
+#endif
 
 instance MonadThrow (ST s) where
   throwM = unsafeIOToST . ControlException.throwIO
+#if MIN_VERSION_base(4,21,0)
+  rethrowM = unsafeIOToST . ControlException.rethrowIO
+#endif
 
 instance MonadThrow STM where
   throwM = STM.throwSTM
@@ -597,12 +636,6 @@
         return (a, s2, mappend w1 w2))
     return ((b, c), s3, w123)
 
--- Transformers which are only instances of MonadThrow and MonadCatch, not MonadMask
-instance MonadThrow m => MonadThrow (ListT m) where
-  throwM = lift . throwM
-instance MonadCatch m => MonadCatch (ListT m) where
-  catch (ListT m) f = ListT $ catch m (runListT . f)
-
 -- | Throws exceptions into the base monad.
 instance MonadThrow m => MonadThrow (MaybeT m) where
   throwM = lift . throwM
@@ -639,42 +672,6 @@
     return ((,) <$> eb <*> ec)
 
 -- | Throws exceptions into the base monad.
-instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where
-  throwM = lift . throwM
--- | Catches exceptions from the base monad.
-instance (Error e, MonadCatch m) => MonadCatch (ErrorT e m) where
-  catch (ErrorT m) f = ErrorT $ catch m (runErrorT . f)
-instance (Error e, MonadMask m) => MonadMask (ErrorT e m) where
-  mask f = ErrorT $ mask $ \u -> runErrorT $ f (q u)
-    where
-      q :: (m (Either e a) -> m (Either e a))
-        -> ErrorT e m a -> ErrorT e m a
-      q u (ErrorT b) = ErrorT (u b)
-  uninterruptibleMask f = ErrorT $ uninterruptibleMask $ \u -> runErrorT $ f (q u)
-    where
-      q :: (m (Either e a) -> m (Either e a))
-        -> ErrorT e m a -> ErrorT e m a
-      q u (ErrorT b) = ErrorT (u b)
-
-  generalBracket acquire release use = ErrorT $ do
-    (eb, ec) <- generalBracket
-      (runErrorT acquire)
-      (\eresource exitCase -> case eresource of
-        Left e -> return (Left e) -- nothing to release, acquire didn't succeed
-        Right resource -> case exitCase of
-          ExitCaseSuccess (Right b) -> runErrorT (release resource (ExitCaseSuccess b))
-          ExitCaseException e       -> runErrorT (release resource (ExitCaseException e))
-          _                         -> runErrorT (release resource ExitCaseAbort))
-      (either (return . Left) (runErrorT . use))
-    return $ do
-      -- The order in which we perform those two 'Either' effects determines
-      -- which error will win if they are both 'Left's. We want the error from
-      -- 'release' to win.
-      c <- ec
-      b <- eb
-      return (b, c)
-
--- | Throws exceptions into the base monad.
 instance MonadThrow m => MonadThrow (ExceptT e m) where
   throwM = lift . throwM
 -- | Catches exceptions from the base monad.
@@ -719,6 +716,63 @@
 -- I don't believe any valid of MonadCatch exists for ContT.
 -- instance MonadCatch m => MonadCatch (ContT r m) where
 
+#if MIN_VERSION_transformers(0,5,6)
+instance (Monoid w, MonadThrow m) => MonadThrow (AccumT w m) where
+  throwM = lift . throwM
+
+instance (MonadCatch m, Monoid w) => MonadCatch (AccumT w m) where
+  catch (AccumT m) f = AccumT $ \w -> catch (m w) $ \e -> runAccumT (f e) w
+
+instance (MonadMask m, Monoid w) => MonadMask (AccumT w m) where
+  mask f = AccumT $ \w -> mask $ \g -> flip runAccumT w $ f $ \(AccumT m) -> AccumT $ \w' -> g $ m w'
+  uninterruptibleMask f = AccumT $ \w -> uninterruptibleMask $ \g -> flip runAccumT w $ f $ \(AccumT m) -> AccumT $ \w' -> g $ m w'
+  generalBracket m f g = AccumT $ \w -> (\(b, (c, w')) -> ((b, c), w')) <$> generalBracket (runAccumT m w) (\(a, w') exitCase -> runAccumT (f a exitCase) (w <> w')) (\(a, w') -> evalAccumT (g a) (w <> w'))
+#endif
+
+#if !MIN_VERSION_transformers(0,6,0)
+-- | Throws exceptions into the base monad.
+instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where
+  throwM = lift . throwM
+-- | Catches exceptions from the base monad.
+instance (Error e, MonadCatch m) => MonadCatch (ErrorT e m) where
+  catch (ErrorT m) f = ErrorT $ catch m (runErrorT . f)
+instance (Error e, MonadMask m) => MonadMask (ErrorT e m) where
+  mask f = ErrorT $ mask $ \u -> runErrorT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ErrorT e m a -> ErrorT e m a
+      q u (ErrorT b) = ErrorT (u b)
+  uninterruptibleMask f = ErrorT $ uninterruptibleMask $ \u -> runErrorT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ErrorT e m a -> ErrorT e m a
+      q u (ErrorT b) = ErrorT (u b)
+
+  generalBracket acquire release use = ErrorT $ do
+    (eb, ec) <- generalBracket
+      (runErrorT acquire)
+      (\eresource exitCase -> case eresource of
+        Left e -> return (Left e) -- nothing to release, acquire didn't succeed
+        Right resource -> case exitCase of
+          ExitCaseSuccess (Right b) -> runErrorT (release resource (ExitCaseSuccess b))
+          ExitCaseException e       -> runErrorT (release resource (ExitCaseException e))
+          _                         -> runErrorT (release resource ExitCaseAbort))
+      (either (return . Left) (runErrorT . use))
+    return $ do
+      -- The order in which we perform those two 'Either' effects determines
+      -- which error will win if they are both 'Left's. We want the error from
+      -- 'release' to win.
+      c <- ec
+      b <- eb
+      return (b, c)
+
+-- Transformers which are only instances of MonadThrow and MonadCatch, not MonadMask
+instance MonadThrow m => MonadThrow (ListT m) where
+  throwM = lift . throwM
+instance MonadCatch m => MonadCatch (ListT m) where
+  catch (ListT m) f = ListT $ catch m (runListT . f)
+#endif
+
 ------------------------------------------------------------------------------
 -- $utilities
 -- These functions follow those from "Control.Exception", except that they are
@@ -727,72 +781,72 @@
 ------------------------------------------------------------------------------
 
 -- | Like 'mask', but does not pass a @restore@ action to the argument.
-mask_ :: MonadMask m => m a -> m a
-mask_ io = mask $ \_ -> io
+mask_ :: (HasCallStack, MonadMask m) => m a -> m a
+mask_ io = withFrozenCallStack (\f -> mask (\x -> f x)) (\_ -> io)
 
 -- | Like 'uninterruptibleMask', but does not pass a @restore@ action to the
 -- argument.
-uninterruptibleMask_ :: MonadMask m => m a -> m a
-uninterruptibleMask_ io = uninterruptibleMask $ \_ -> io
+uninterruptibleMask_ :: (HasCallStack, MonadMask m) => m a -> m a
+uninterruptibleMask_ io = withFrozenCallStack (\f -> uninterruptibleMask (\x -> f x)) (\_ -> io)
 
 -- | Catches all exceptions, and somewhat defeats the purpose of the extensible
 -- exception system. Use sparingly.
 --
 -- /NOTE/ This catches all /exceptions/, but if the monad supports other ways of
 -- aborting the computation, those other kinds of errors will not be caught.
-catchAll :: MonadCatch m => m a -> (SomeException -> m a) -> m a
-catchAll = catch
+catchAll :: (HasCallStack, MonadCatch m) => m a -> (SomeException -> m a) -> m a
+catchAll = withFrozenCallStack catch
 
 -- | Catch all 'IOError' (eqv. 'IOException') exceptions. Still somewhat too
 -- general, but better than using 'catchAll'. See 'catchIf' for an easy way
 -- of catching specific 'IOError's based on the predicates in "System.IO.Error".
-catchIOError :: MonadCatch m => m a -> (IOError -> m a) -> m a
-catchIOError = catch
+catchIOError :: (HasCallStack, MonadCatch m) => m a -> (IOError -> m a) -> m a
+catchIOError = withFrozenCallStack catch
 
 -- | Catch exceptions only if they pass some predicate. Often useful with the
 -- predicates for testing 'IOError' values in "System.IO.Error".
-catchIf :: (MonadCatch m, Exception e) =>
+catchIf :: (HasCallStack, MonadCatch m, Exception e) =>
     (e -> Bool) -> m a -> (e -> m a) -> m a
-catchIf f a b = a `catch` \e -> if f e then b e else throwM e
+catchIf f a b = withFrozenCallStack catch a (\e -> if f e then b e else throwM e)
 
 -- | A more generalized way of determining which exceptions to catch at
 -- run time.
-catchJust :: (MonadCatch m, Exception e) =>
+catchJust :: (HasCallStack, MonadCatch m, Exception e) =>
     (e -> Maybe b) -> m a -> (b -> m a) -> m a
-catchJust f a b = a `catch` \e -> maybe (throwM e) b $ f e
+catchJust f a b = withFrozenCallStack catch a (\e -> maybe (throwM e) b $ f e)
 
 -- | Flipped 'catch'. See "Control.Exception"'s 'ControlException.handle'.
-handle :: (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
-handle = flip catch
+handle :: (HasCallStack, MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
+handle = flip (withFrozenCallStack catch)
 {-# INLINE handle #-}
 
 -- | Flipped 'catchIOError'
-handleIOError :: MonadCatch m => (IOError -> m a) -> m a -> m a
-handleIOError = handle
+handleIOError :: (HasCallStack, MonadCatch m) => (IOError -> m a) -> m a -> m a
+handleIOError = withFrozenCallStack handle
 
 -- | Flipped 'catchAll'
-handleAll :: MonadCatch m => (SomeException -> m a) -> m a -> m a
-handleAll = handle
+handleAll :: (HasCallStack, MonadCatch m) => (SomeException -> m a) -> m a -> m a
+handleAll = withFrozenCallStack handle
 
 -- | Flipped 'catchIf'
-handleIf :: (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
-handleIf f = flip (catchIf f)
+handleIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
+handleIf f = flip (withFrozenCallStack catchIf f)
 
 -- | Flipped 'catchJust'. See "Control.Exception"'s 'ControlException.handleJust'.
-handleJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
-handleJust f = flip (catchJust f)
+handleJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
+handleJust f = flip (withFrozenCallStack catchJust f)
 {-# INLINE handleJust #-}
 
 -- | Similar to 'catch', but returns an 'Either' result. See "Control.Exception"'s
 -- 'Control.Exception.try'.
-try :: (MonadCatch m, Exception e) => m a -> m (Either e a)
-try a = catch (Right `liftM` a) (return . Left)
+try :: (HasCallStack, MonadCatch m, Exception e) => m a -> m (Either e a)
+try a = withFrozenCallStack catch (Right `liftM` a) (return . Left)
 
 -- | A variant of 'try' that takes an exception predicate to select
 -- which exceptions are caught. See "Control.Exception"'s 'ControlException.tryJust'
-tryJust :: (MonadCatch m, Exception e) =>
+tryJust :: (HasCallStack, MonadCatch m, Exception e) =>
     (e -> Maybe b) -> m a -> m (Either b a)
-tryJust f a = catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e))
+tryJust f a = withFrozenCallStack catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e))
 
 -- | Generalized version of 'ControlException.Handler'
 data Handler m a = forall e . ControlException.Exception e => Handler (e -> m a)
@@ -801,8 +855,8 @@
   fmap f (Handler h) = Handler (liftM f . h)
 
 -- | Catches different sorts of exceptions. See "Control.Exception"'s 'ControlException.catches'
-catches :: (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
-catches a hs = a `catch` handler
+catches :: (HasCallStack, Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
+catches a hs = withFrozenCallStack catch a handler
   where
     handler e = foldr probe (throwM e) hs
       where
@@ -814,8 +868,8 @@
 -- /NOTE/ The action is only run if an /exception/ is thrown. If the monad
 -- supports other ways of aborting the computation, the action won't run if
 -- those other kinds of errors are thrown. See 'onError'.
-onException :: MonadCatch m => m a -> m b -> m a
-onException action handler = action `catchAll` \e -> handler >> throwM e
+onException :: (HasCallStack, MonadCatch m) => m a -> m b -> m a
+onException action handler = withFrozenCallStack catchAll action (\e -> handler >> throwM e)
 
 -- | Run an action only if an error is thrown in the main action. Unlike
 -- 'onException', this works with every kind of error, not just exceptions. For
@@ -828,8 +882,8 @@
 -- except that 'onError' has a more constrained type.
 --
 -- @since 0.10.0
-onError :: MonadMask m => m a -> m b -> m a
-onError action handler = bracketOnError (return ()) (const handler) (const action)
+onError :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+onError action handler = withFrozenCallStack bracketOnError (return ()) (const handler) (const action)
 
 -- | Generalized abstracted pattern of safe resource acquisition and release
 -- in the face of errors. The first action \"acquires\" some value, which
@@ -844,25 +898,25 @@
 -- signature from "Control.Exception"), and is often more convenient to use. By
 -- contrast, 'generalBracket' is more expressive, allowing us to implement
 -- other functions like 'bracketOnError'.
-bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
-bracket acquire release = liftM fst . generalBracket
+bracket :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+bracket acquire release = liftM fst . withFrozenCallStack generalBracket
   acquire
   (\a _exitCase -> release a)
 
 -- | Version of 'bracket' without any value being passed to the second and
 -- third actions.
-bracket_ :: MonadMask m => m a -> m c -> m b -> m b
-bracket_ before after action = bracket before (const after) (const action)
+bracket_ :: (HasCallStack, MonadMask m) => m a -> m c -> m b -> m b
+bracket_ before after action = withFrozenCallStack bracket before (const after) (const action)
 
 -- | Perform an action with a finalizer action that is run, even if an
 -- error occurs.
-finally :: MonadMask m => m a -> m b -> m a
-finally action finalizer = bracket_ (return ()) finalizer action
+finally :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+finally action finalizer = withFrozenCallStack bracket_ (return ()) finalizer action
 
 -- | Like 'bracket', but only performs the final action if an error is
 -- thrown by the in-between computation.
-bracketOnError :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
-bracketOnError acquire release = liftM fst . generalBracket
+bracketOnError :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+bracketOnError acquire release = liftM fst . withFrozenCallStack generalBracket
   acquire
   (\a exitCase -> case exitCase of
     ExitCaseSuccess _ -> return ()
diff --git a/src/Control/Monad/Catch/Pure.hs b/src/Control/Monad/Catch/Pure.hs
--- a/src/Control/Monad/Catch/Pure.hs
+++ b/src/Control/Monad/Catch/Pure.hs
@@ -5,19 +5,8 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
-
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE Trustworthy #-}
-#endif
 
-#ifndef MIN_VERSION_transformers
-#define MIN_VERSION_transformers(x,y,z) 1
-#endif
-
-#ifndef MIN_VERSION_mtl
-#define MIN_VERSION_mtl(x,y,z) 1
-#endif
-
 --------------------------------------------------------------------
 -- |
 -- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012
@@ -46,22 +35,24 @@
   , module Control.Monad.Catch
   ) where
 
-#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 706)
 import Prelude hiding (foldr)
-#else
-import Prelude hiding (catch, foldr)
-#endif
 
 import Control.Applicative
 import Control.Monad.Catch
 import qualified Control.Monad.Fail as Fail
-import Control.Monad.Reader as Reader
-import Control.Monad.RWS
-#if __GLASGOW_HASKELL__ < 710
-import Data.Foldable
-#endif
+import Control.Monad.Fix (MonadFix(..))
+import Control.Monad.IO.Class (MonadIO(..))
+import Control.Monad (MonadPlus(..), ap, liftM)
+import Control.Monad.Reader (MonadReader(..))
+import Control.Monad.RWS (MonadRWS)
+import Control.Monad.State (MonadState(..))
+import Control.Monad.Trans.Class (MonadTrans(..))
+import Control.Monad.Writer (MonadWriter(..))
 import Data.Functor.Identity
 import Data.Traversable as Traversable
+#if defined(__MHS__)
+import Data.Foldable
+#endif
 
 ------------------------------------------------------------------------------
 -- $mtl
@@ -70,7 +61,7 @@
 
 ------------------------------------------------------------------------------
 -- $transformer
--- The @transformers@-style monad transfomer
+-- The @transformers@-style monad transformer
 ------------------------------------------------------------------------------
 
 -- | Add 'Exception' handling abilities to a 'Monad'.
@@ -185,9 +176,7 @@
 instance MonadState s m => MonadState s (CatchT m) where
   get = lift get
   put = lift . put
-#if MIN_VERSION_mtl(2,1,0)
   state = lift . state
-#endif
 
 instance MonadReader e m => MonadReader e (CatchT m) where
   ask = lift ask
@@ -203,9 +192,7 @@
     return $! case a of
         Left  l      -> (Left  l, id)
         Right (r, f) -> (Right r, f)
-#if MIN_VERSION_mtl(2,1,0)
   writer aw = CatchT (Right `liftM` writer aw)
-#endif
 
 instance MonadRWS r w s m => MonadRWS r w s (CatchT m)
 
diff --git a/tests/Control/Monad/Catch/Tests.hs b/tests/Control/Monad/Catch/Tests.hs
--- a/tests/Control/Monad/Catch/Tests.hs
+++ b/tests/Control/Monad/Catch/Tests.hs
@@ -4,44 +4,44 @@
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE CPP #-}
 
-module Control.Monad.Catch.Tests (tests) where
-
-#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
-import Prelude hiding (catch)
+#if !(MIN_VERSION_transformers(0,6,0))
+{-# OPTIONS_GHC -Wno-deprecations #-}
 #endif
 
-import Control.Applicative ((<*>))
+module Control.Monad.Catch.Tests (tests) where
+
 import Control.Monad (unless)
-import Data.Data (Data, Typeable)
+import Data.Data (Data)
 import Data.IORef (newIORef, writeIORef, readIORef)
 
 import Control.Monad.Trans.Class (lift)
 import Control.Monad.Trans.Identity (IdentityT(..))
 import Control.Monad.Reader (ReaderT(..))
-import Control.Monad.List (ListT(..))
 import Control.Monad.Trans.Maybe (MaybeT(..))
-import Control.Monad.Error (ErrorT(..))
 import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
 import Control.Monad.STM (STM, atomically)
 --import Control.Monad.Cont (ContT(..))
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-import Test.QuickCheck (Property, once)
+import Test.QuickCheck (Property, ioProperty, once)
 import Test.QuickCheck.Monadic (monadic, run, assert)
-import Test.QuickCheck.Property (morallyDubiousIOProperty)
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.HUnit (testCase)
+import Test.Tasty.QuickCheck (testProperty)
 import qualified Control.Monad.State.Lazy as LazyState
 import qualified Control.Monad.State.Strict as StrictState
 import qualified Control.Monad.Writer.Lazy as LazyWriter
 import qualified Control.Monad.Writer.Strict as StrictWriter
 import qualified Control.Monad.RWS.Lazy as LazyRWS
 import qualified Control.Monad.RWS.Strict as StrictRWS
+#if !(MIN_VERSION_transformers(0,6,0))
+import Control.Monad.Trans.Error (ErrorT(..))
+import Control.Monad.Trans.List (ListT(..))
+#endif
 
 import Control.Monad.Catch
 import Control.Monad.Catch.Pure
 
 data TestException = TestException String
-    deriving (Show, Eq, Data, Typeable)
+    deriving (Show, Eq, Data)
 
 instance Exception TestException
 
@@ -85,11 +85,11 @@
     monadic (mspecRunner mspec) $ do
         effectWasPerformed <- run $ do
           (effect, detector) <- effectDetector
-          runExceptT $ ExceptT (return $ Left ()) `finally` lift effect
+          _ <- runExceptT $ ExceptT (return $ Left ()) `finally` lift effect
           detector
         assert effectWasPerformed
 
-tests :: Test
+tests :: TestTree
 tests = testGroup "Control.Monad.Catch.Tests" $
    ([ mkMonadCatch
     , mkCatchJust
@@ -111,9 +111,11 @@
         , SomeMSpec mspecLazyRWSTIO
         , SomeMSpec mspecStrictRWSTIO
 
-        , SomeMSpec mspecListTIO
         , SomeMSpec mspecMaybeTIO
+#if !(MIN_VERSION_transformers(0,6,0))
         , SomeMSpec mspecErrorTIO
+        , SomeMSpec mspecListTIO
+#endif
         , SomeMSpec mspecSTM
         --, SomeMSpec mspecContTIO
 
@@ -148,15 +150,17 @@
     mspecStrictRWSTIO :: MSpec (StrictRWS.RWST () () Bool IO)
     mspecStrictRWSTIO = MSpec "StrictRWS.RWST IO" $ \m -> io $ fmap tfst $ StrictRWS.evalRWST m () False
 
-    mspecListTIO :: MSpec (ListT IO)
-    mspecListTIO = MSpec "ListT IO" $ \m -> io $ fmap (\[x] -> x) (runListT m)
-
     mspecMaybeTIO :: MSpec (MaybeT IO)
     mspecMaybeTIO = MSpec "MaybeT IO" $ \m -> io $ fmap (maybe undefined id) (runMaybeT m)
 
+#if !(MIN_VERSION_transformers(0,6,0))
     mspecErrorTIO :: MSpec (ErrorT String IO)
     mspecErrorTIO = MSpec "ErrorT IO" $ \m -> io $ fmap (either error id) (runErrorT m)
 
+    mspecListTIO :: MSpec (ListT IO)
+    mspecListTIO = MSpec "ListT IO" $ \m -> io $ fmap (foldr const undefined) (runListT m)
+#endif
+
     mspecSTM :: MSpec STM
     mspecSTM = MSpec "STM" $ io . atomically
 
@@ -172,7 +176,7 @@
     tfst :: (Property, ()) -> Property = fst
     fromRight (Left _) = error "fromRight"
     fromRight (Right a) = a
-    io = morallyDubiousIOProperty
+    io = ioProperty
 
     detectableEffects =
         [ SomeDetectableEffect $ detectableEffectIO
@@ -183,39 +187,54 @@
         ]
 
     detectableEffectIO :: DetectableEffect IO
-    detectableEffectIO = DetectableEffect mspecIO $ do
-      ref <- newIORef False
-      return (writeIORef ref True, readIORef ref)
+    detectableEffectIO = DetectableEffect
+      { detectableEffectMSpec = mspecIO
+      , detectableEffectEffectDetector = do
+          ref <- newIORef False
+          return (writeIORef ref True, readIORef ref)
+      }
 
     detectableEffectLazyStateTIO :: DetectableEffect (LazyState.StateT Bool IO)
-    detectableEffectLazyStateTIO = DetectableEffect mspecLazyStateTIO $ do
-      LazyState.put False
-      return (LazyState.put True, LazyState.get)
+    detectableEffectLazyStateTIO = DetectableEffect
+      { detectableEffectMSpec = mspecLazyStateTIO
+      , detectableEffectEffectDetector = do
+          LazyState.put False
+          return (LazyState.put True, LazyState.get)
+      }
 
     detectableEffectStrictStateTIO :: DetectableEffect (StrictState.StateT Bool IO)
-    detectableEffectStrictStateTIO = DetectableEffect mspecStrictStateTIO $ do
-      StrictState.put False
-      return (StrictState.put True, StrictState.get)
+    detectableEffectStrictStateTIO = DetectableEffect
+      { detectableEffectMSpec = mspecStrictStateTIO
+      , detectableEffectEffectDetector = do
+          StrictState.put False
+          return (StrictState.put True, StrictState.get)
+      }
 
     detectableEffectLazyRWSTIO :: DetectableEffect (LazyRWS.RWST () () Bool IO)
-    detectableEffectLazyRWSTIO = DetectableEffect mspecLazyRWSTIO $ do
-      LazyRWS.put False
-      return (LazyRWS.put True, LazyRWS.get)
+    detectableEffectLazyRWSTIO = DetectableEffect
+      { detectableEffectMSpec = mspecLazyRWSTIO
+      , detectableEffectEffectDetector = do
+          LazyRWS.put False
+          return (LazyRWS.put True, LazyRWS.get)
+      }
 
     detectableEffectStrictRWSTIO :: DetectableEffect (StrictRWS.RWST () () Bool IO)
-    detectableEffectStrictRWSTIO = DetectableEffect mspecStrictRWSTIO $ do
-      StrictRWS.put False
-      return (StrictRWS.put True, StrictRWS.get)
+    detectableEffectStrictRWSTIO = DetectableEffect
+      { detectableEffectMSpec = mspecStrictRWSTIO
+      , detectableEffectEffectDetector = do
+          StrictRWS.put False
+          return (StrictRWS.put True, StrictRWS.get)
+      }
 
     mkMonadCatch = mkMSpecTest "MonadCatch" testMonadCatch
     mkCatchJust = mkMSpecTest "catchJust" testCatchJust
     mkDetectableEffect = mkDetectableEffectTest "effect during release" testDetectableEffect
 
-    mkMSpecTest :: String -> (SomeMSpec -> Property) -> SomeMSpec -> Test
+    mkMSpecTest :: String -> (SomeMSpec -> Property) -> SomeMSpec -> TestTree
     mkMSpecTest name test = \someMSpec@(SomeMSpec spec) ->
         testProperty (name ++ " " ++ mspecName spec) $ once $ test someMSpec
 
-    mkDetectableEffectTest :: String -> (SomeDetectableEffect -> Property) -> SomeDetectableEffect -> Test
+    mkDetectableEffectTest :: String -> (SomeDetectableEffect -> Property) -> SomeDetectableEffect -> TestTree
     mkDetectableEffectTest name test = \someDetectableEffect@(SomeDetectableEffect detectableEffect) ->
         let testName = name ++ " " ++ mspecName (detectableEffectMSpec detectableEffect)
         in testProperty testName $ once $ test someDetectableEffect
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -1,10 +1,11 @@
 module Main where
 
-import Test.Framework (defaultMain)
+import Test.Tasty (defaultMain, testGroup)
 
 import qualified Control.Monad.Catch.Tests
 
 main :: IO ()
-main = defaultMain
+main = defaultMain $
+  testGroup "exceptions"
     [ Control.Monad.Catch.Tests.tests
     ]
diff --git a/travis/cabal-apt-install b/travis/cabal-apt-install
deleted file mode 100644
--- a/travis/cabal-apt-install
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-set -eu
-
-APT="sudo apt-get -q -y"
-CABAL_INSTALL_DEPS="cabal install --only-dependencies --force-reinstall"
-
-$APT update
-$APT install dctrl-tools
-
-# Find potential system packages to satisfy cabal dependencies
-deps()
-{
-	local M='^\([^ ]\+\)-[0-9.]\+ (.*$'
-	local G=' -o ( -FPackage -X libghc-\L\1\E-dev )'
-	local E="$($CABAL_INSTALL_DEPS "$@" --dry-run -v 2> /dev/null \
-		| sed -ne "s/$M/$G/p" | sort -u)"
-	grep-aptavail -n -sPackage \( -FNone -X None \) $E | sort -u
-}
-
-$APT install $(deps "$@") libghc-quickcheck2-dev # QuickCheck is special
-$CABAL_INSTALL_DEPS "$@" # Install the rest via Hackage
-
-if ! $APT install hlint ; then
-	$APT install $(deps hlint)
-	cabal install hlint
-fi
-
diff --git a/travis/config b/travis/config
deleted file mode 100644
--- a/travis/config
+++ /dev/null
@@ -1,16 +0,0 @@
--- This provides a custom ~/.cabal/config file for use when hackage is down that should work on unix
---
--- This is particularly useful for travis-ci to get it to stop complaining
--- about a broken build when everything is still correct on our end.
---
--- This uses Luite Stegeman's mirror of hackage provided by his 'hdiff' site instead
---
--- To enable this, uncomment the before_script in .travis.yml
-
-remote-repo: hdiff.luite.com:http://hdiff.luite.com/packages/archive
-remote-repo-cache: ~/.cabal/packages
-world-file: ~/.cabal/world
-build-summary: ~/.cabal/logs/build.log
-remote-build-reporting: anonymous
-install-dirs user
-install-dirs global
