diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+## 0.1.5.0
+
+* Re-export `Control.Exception.assert`
+* Add `throwString`
+
 ## 0.1.4.0
 
 * Add `catchJust`, `handleJust`, and `tryJust`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,19 +2,18 @@
 
 *Safe, consistent, and easy exception handling*
 
-__NOTE__: This library is early in its development, and there may be some
-changes in the near future. See [possible future
-changes](#possible-future-changes).
-
 [![Build Status](https://travis-ci.org/fpco/safe-exceptions.svg?branch=master)](https://travis-ci.org/fpco/safe-exceptions)
 
 Runtime exceptions - as exposed in `base` by the `Control.Exception`
 module - have long been an intimidating part of the Haskell
 ecosystem. This package, and this README for the package, are intended
-to overcome this. By providing an API that encourages best practices,
-and explaining the corner cases clearly, the hope is to turn what was
-previously something scary into an aspect of Haskell everyone feels
-safe using.
+to overcome this. It provides a safe and simple API on top of the
+existing exception handling machinery. The API is equivalent to the
+underlying implementation in terms of power but encourages best
+practices to minimize the chances of getting the exception handling
+wrong.  By doing so and explaining the corner cases clearly, the hope is
+to turn what was previously something scary into an aspect of Haskell
+everyone feels safe using.
 
 ## Goals
 
@@ -71,6 +70,9 @@
 Hopefully this will be able to get you up-and-running quickly. You may
 also be interested in
 [browsing through the cookbook](https://github.com/fpco/safe-exceptions/blob/master/COOKBOOK.md).
+There is also an
+[exception safety tutorial on haskell-lang.org](https://haskell-lang.org/tutorial/exception-safety)
+which is based on this package.
 
 ## Terminology
 
@@ -165,8 +167,8 @@
 Therefore, this package takes the approach of trusting type
 information to determine if an exception is asynchronous or
 synchronous. The details are less interesting to a user, but the
-basics are: we leverage the extensible extension system in GHC and
-state that any extension type which is a child of `SomeAsyncException`
+basics are: we leverage the extensible exception system in GHC and
+state that any exception type which is a child of `SomeAsyncException`
 is an async exception. All other exception types are assumed to be
 synchronous.
 
@@ -321,30 +323,3 @@
   kill signal from another thread or the user (via Ctrl-C), we would
   like to be able to detect that we entered a deadlock condition and do
   something intelligent in an application.
-
-## Possible future changes
-
-### Interruptible vs uninterruptible masking
-
-This discussion is now being tracked at:
-https://github.com/fpco/safe-exceptions/issues/3
-
-In `Control.Exception`, allocation functions and cleanup handlers in
-combinators like `bracket` are masked using the (interruptible) `mask`
-function, in contrast to `uninterruptibleMask`. There have been some debates
-about the correctness of this in the past, notably [a libraries mailing list
-discussion kicked off by Eyal
-Lotem](https://mail.haskell.org/pipermail/libraries/2014-September/023675.html).
-It seems that general consensus is:
-
-* `uninterruptibleMask` is a better choice
-* But changing the core library like this would potentially break too many
-  programs
-
-In its current version, this library uses `mask` (interruptible) for allocation
-functions and `uninterruptibleMask` cleanup handlers. This is a debatable
-decision (and one worth debating!). An example of alternatives would be:
-
-* Use `uninterruptibleMask` for both allocation and cleanup pieces
-* Match `Control.Exception`'s behavior
-* Provide two versions of each function, or possibly two modules
diff --git a/safe-exceptions.cabal b/safe-exceptions.cabal
--- a/safe-exceptions.cabal
+++ b/safe-exceptions.cabal
@@ -1,5 +1,5 @@
 name:                safe-exceptions
-version:             0.1.4.0
+version:             0.1.5.0
 synopsis:            Safe, consistent, and easy exception handling
 description:         Please see README.md
 homepage:            https://github.com/fpco/safe-exceptions#readme
diff --git a/src/Control/Exception/Safe.hs b/src/Control/Exception/Safe.hs
--- a/src/Control/Exception/Safe.hs
+++ b/src/Control/Exception/Safe.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ImplicitParams #-}
 -- | Please see the README.md file in the safe-exceptions repo for
 -- information on how to use this module. Relevant links:
 --
@@ -13,6 +14,8 @@
       throw
     , throwIO
     , throwM
+    , throwString
+    , StringException (..)
     , throwTo
     , impureThrow
       -- * Catching (with recovery)
@@ -77,6 +80,7 @@
     , SomeException (..)
     , SomeAsyncException (..)
     , E.IOException
+    , E.assert
 #if !MIN_VERSION_base(4,8,0)
     , displayException
 #endif
@@ -91,6 +95,11 @@
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Data.Typeable (Typeable, cast)
 
+#if MIN_VERSION_base(4,9,0)
+import GHC.Stack (prettySrcLoc)
+import GHC.Stack.Types (HasCallStack, CallStack, getCallStack)
+#endif
+
 -- | Synchronously throw the given exception
 --
 -- @since 0.1.0.0
@@ -109,8 +118,65 @@
 throwM :: (C.MonadThrow m, Exception e) => e -> m a
 throwM = throw
 
--- | Throw an asynchronous exception to another thread
+-- | A convenience function for throwing a user error. This is useful
+-- for cases where it would be too high a burden to define your own
+-- exception type.
 --
+-- This throws an exception of type 'StringException'. When GHC
+-- supports it (base 4.9 and GHC 8.0 and onward), it includes a call
+-- stack.
+--
+-- @since 0.1.5.0
+#if MIN_VERSION_base(4,9,0)
+throwString :: (C.MonadThrow m, HasCallStack) => String -> m a
+throwString s = throwM (StringException s ?callStack)
+#else
+throwString :: C.MonadThrow m => String -> m a
+throwString s = throwM (StringException s ())
+#endif
+
+-- | Exception type thrown by 'throwString'.
+--
+-- Note that the second field of the data constructor depends on
+-- GHC/base version. For base 4.9 and GHC 8.0 and later, the second
+-- field is a call stack. Previous versions of GHC and base do not
+-- support call stacks, and the field is simply unit (provided to make
+-- pattern matching across GHC versions easier).
+--
+-- @since 0.1.5.0
+#if MIN_VERSION_base(4,9,0)
+data StringException = StringException String CallStack
+  deriving Typeable
+
+instance Show StringException where
+    show (StringException s cs) = concat
+        $ "Control.Exception.Safe.throwString called with:\n\n"
+        : s
+        : "\nCalled from:\n"
+        : map go (getCallStack cs)
+      where
+        go (x, y) = concat
+          [ "  "
+          , x
+          , " ("
+          , prettySrcLoc y
+          , ")\n"
+          ]
+#else
+data StringException = StringException String ()
+  deriving Typeable
+
+instance Show StringException where
+    show (StringException s _) = "Control.Exception.Safe.throwString called with:\n\n" ++ s
+#endif
+instance Exception StringException
+
+-- | Throw an asynchronous exception to another thread.
+--
+-- Synchronously typed exceptions will be wrapped into an
+-- `AsyncExceptionWrapper`, see
+-- <https://github.com/fpco/safe-exceptions#determining-sync-vs-async>
+--
 -- It's usually a better idea to use the async package, see
 -- <https://github.com/fpco/safe-exceptions#quickstart>
 --
@@ -325,7 +391,7 @@
                 C.try $ C.uninterruptibleMask_ $ after x
             C.throwM e1
         Right y -> do
-            C.uninterruptibleMask_ $ after x
+            _ <- C.uninterruptibleMask_ $ after x
             return y
 
 -- | Async safe version of 'E.bracket_'
@@ -346,7 +412,7 @@
             _ :: Either SomeException b <- C.try after
             C.throwM e1
         Right x -> do
-            after
+            _ <- after
             return x
 
 -- | Async safe version of 'E.bracketOnError'
diff --git a/test/Control/Exception/SafeSpec.hs b/test/Control/Exception/SafeSpec.hs
--- a/test/Control/Exception/SafeSpec.hs
+++ b/test/Control/Exception/SafeSpec.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 module Control.Exception.SafeSpec (spec) where
@@ -12,6 +13,9 @@
 import System.IO.Unsafe (unsafePerformIO)
 import System.Timeout (timeout)
 import Test.Hspec
+#if !MIN_VERSION_base(4,9,0)
+import System.IO.Error (isUserError)
+#endif
 
 newtype ExceptionPred = ExceptionPred { getExceptionPred :: Maybe () } deriving (Show, Eq, Typeable)
 
@@ -124,3 +128,7 @@
         let ex = ExceptionPred Nothing
         res <- try (catchJust getExceptionPred (throw ex) (return . Just))
         res `shouldBe` Left ex
+
+    describe "throwString" $ do
+      it "is a StringException" $
+        throwString "foo" `catch` \(StringException _ _) -> return () :: IO ()
