diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,8 @@
+## Changes in 0.11.2 [2020.09.30]
+ - Sync with `base-4.15`/GHC 9.0
+ - Backport `singleton` to `Data.List` and `Data.List.NonEmpty`
+ - Backport `hGetContents'`, `getContents'`, and `readFile'` added to `System.IO`
+
 ## Changes in 0.11.1 [2020.01.27]
  - Sync with `base-4.14`/GHC 8.10
  - Backport `isResourceVanishedError`, `resourceVanishedErrorType`, and
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -152,6 +152,8 @@
  * `RuntimeRep`-polymorphic `throw` to `Control.Exception.Compat`
  * `isResourceVanishedError`, `resourceVanishedErrorType`, and
    `isResourceVanishedErrorType` to `System.IO.Error.Compat`
+ * `singleton` to `Data.List.Compat` and `Data.List.NonEmpty.Compat`
+ * `hGetContents'`, `getContents'`, and `readFile'` to `System.IO`
 
 ## What is not covered
 
@@ -304,6 +306,7 @@
 
 ## Supported versions of GHC/`base`
 
+ * `ghc-9.0.*`  / `base-4.15.*`
  * `ghc-8.10.*` / `base-4.14.*`
  * `ghc-8.8.*`  / `base-4.13.*`
  * `ghc-8.6.*`  / `base-4.12.*`
diff --git a/base-compat.cabal b/base-compat.cabal
--- a/base-compat.cabal
+++ b/base-compat.cabal
@@ -1,5 +1,5 @@
 name:             base-compat
-version:          0.11.1
+version:          0.11.2
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2012-2018 Simon Hengel,
@@ -12,7 +12,7 @@
                   João Cristóvão <jmacristovao@gmail.com>,
                   Ryan Scott <ryan.gl.scott@gmail.com>
 build-type:       Simple
-cabal-version:    >= 1.8
+cabal-version:    >= 1.10
 category:         Compatibility
 synopsis:         A compatibility layer for base
 description:      Provides functions available in later versions of @base@ to
@@ -53,7 +53,7 @@
                   , GHC == 8.2.2
                   , GHC == 8.4.4
                   , GHC == 8.6.5
-                  , GHC == 8.8.2
+                  , GHC == 8.8.3
                   , GHC == 8.10.1
 extra-source-files: CHANGES.markdown, README.markdown
 
@@ -65,6 +65,8 @@
 library
   ghc-options:
       -Wall
+  default-language:
+      Haskell2010
   build-depends:
       base >= 4.3 && < 5
   if !os(windows) && !os(halvm)
@@ -132,6 +134,7 @@
       Prelude.Compat
       System.Environment.Compat
       System.Exit.Compat
+      System.IO.Compat
       System.IO.Error.Compat
       System.IO.Unsafe.Compat
       Text.Read.Compat
@@ -191,6 +194,7 @@
       Prelude.Compat.Repl
       System.Environment.Compat.Repl
       System.Exit.Compat.Repl
+      System.IO.Compat.Repl
       System.IO.Error.Compat.Repl
       System.IO.Unsafe.Compat.Repl
       Text.Read.Compat.Repl
diff --git a/src/Data/List/Compat.hs b/src/Data/List/Compat.hs
--- a/src/Data/List/Compat.hs
+++ b/src/Data/List/Compat.hs
@@ -5,6 +5,10 @@
 #endif
 module Data.List.Compat (
   module Base
+#if !(MIN_VERSION_base(4,15,0))
+, singleton
+#endif
+
 #if !(MIN_VERSION_base(4,11,0))
 , iterate'
 #endif
@@ -234,4 +238,16 @@
 "iterate'"    [~1] forall f x.   iterate' f x = build (\c _n -> iterate'FB c f x)
 "iterate'FB"  [1]                iterate'FB (:) = iterate'
  #-}
+#endif
+
+#if !(MIN_VERSION_base(4,15,0))
+-- | Produce singleton list.
+--
+-- >>> singleton True
+-- [True]
+--
+-- /Since: 4.14.0.0/
+--
+singleton :: a -> [a]
+singleton x = [x]
 #endif
diff --git a/src/Data/List/NonEmpty/Compat.hs b/src/Data/List/NonEmpty/Compat.hs
--- a/src/Data/List/NonEmpty/Compat.hs
+++ b/src/Data/List/NonEmpty/Compat.hs
@@ -22,6 +22,7 @@
   , tail        
   , last        
   , init        
+  , singleton
   , (<|), cons  
   , uncons      
   , unfoldr     
@@ -75,4 +76,12 @@
 
 #if MIN_VERSION_base(4,9,0)
 import Data.List.NonEmpty
+#endif
+
+#if MIN_VERSION_base(4,9,0) && !(MIN_VERSION_base(4,15,0))
+-- | Construct a 'NonEmpty' list from a single element.
+--
+-- /Since: 4.15/
+singleton :: a -> NonEmpty a
+singleton a = a :| []
 #endif
diff --git a/src/System/IO/Compat.hs b/src/System/IO/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/System/IO/Compat.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE CPP, NoImplicitPrelude #-}
+module System.IO.Compat (
+  module Base
+, getContents'
+, hGetContents'
+, readFile'
+) where
+
+import System.IO as Base
+
+#if !(MIN_VERSION_base(4,15,0))
+import Prelude.Compat
+
+-- | The 'getContents'' operation returns all user input as a single string,
+-- which is fully read before being returned
+-- (same as 'hGetContents'' 'stdin').
+--
+-- /Since: 4.15.0.0/
+
+getContents'    :: IO String
+getContents'    =  hGetContents' stdin
+
+-- | The 'readFile'' function reads a file and
+-- returns the contents of the file as a string.
+-- The file is fully read before being returned, as with 'getContents''.
+--
+-- /Since: 4.15.0.0/
+
+readFile'       :: FilePath -> IO String
+readFile' name  =  openFile name ReadMode >>= hGetContents'
+
+-- | The 'hGetContents'' operation reads all input on the given handle
+-- before returning it as a 'String' and closing the handle.
+--
+-- /Since: 4.15.0.0/
+
+hGetContents'   :: Handle -> IO String
+hGetContents' h =  hGetContents h >>= \s -> length s `seq` return s
+ -- NB: The actual implementation of hGetContents' in `base` uses a lot of
+ -- low-level code from GHC.IO.Handle.Text. What's worse, a lot of this
+ -- low-level code isn't exported, so we'd have to reimplement large chunks
+ -- of it in base-compat if we wanted to backport it. For now, I've opted for
+ -- the simpler approach of simply defining hGetContents' in terms of
+ -- hGetContents, which is the approach that the `extra` and `strict` libraries
+ -- use. (Indeed, the code above is taken from `strict`.)
+#endif
diff --git a/src/System/IO/Compat/Repl.hs b/src/System/IO/Compat/Repl.hs
new file mode 100644
--- /dev/null
+++ b/src/System/IO/Compat/Repl.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE PackageImports #-}
+{-# OPTIONS_GHC -fno-warn-dodgy-exports -fno-warn-unused-imports #-}
+-- | Reexports "System.IO.Compat"
+-- from a globally unique namespace.
+module System.IO.Compat.Repl (
+  module System.IO.Compat
+) where
+import "this" System.IO.Compat
