diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,25 @@
 # Revision history for brittany
 
+## 0.12.1.0 -- September 2019
+
+* Support ghc-8.8
+* Support for OverloadedLabels extension
+  (thanks to Evan Rutledge Borden @eborden)
+* Support for Implicit Params extension (thanks to pepe iborra @pepeiborra)
+* Add flag `--no-user-config` to enable only using manually passed config
+* Disable the performance test suite by default to prevent spurious failures
+  on certain CI setups. The github/travis brittany CI still has all tests
+  enabled. See the `brittany-test-perf` flag in the cabal file.
+* Bugfixes:
+    - Fix one wandering-comment bug for let-in expressions
+    - Fix invalid result for prefix operator pattern matches
+    - Fix lambda expression with laziness/strictness annotation
+    - Fix parenthesis handling for infix pattern matches with 3+ arguments
+* Changes to layouting behaviour:
+    - For pattern matching and data/instance definitions, the usage of
+      parenthesis is now "normalized", i.e. superfluous parens are removed by
+      brittany.
+
 ## 0.12.0.0 -- June 2019
 
 * Support for ghc-8.6 (basic support, not necessarily all new syntactic
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
   (but excluding `-XCPP` which is too hard);
 - Retain newlines and comments unmodified;
 - Be clever about using the available horizontal space while not overflowing
-  the column maximum if it cannot be avoided;
+  the column maximum unless it cannot be avoided;
 - Be clever about aligning things horizontally (this can be turned off
   completely however);
 - Have linear complexity in the size of the input.
@@ -74,32 +74,27 @@
     nix-env -i ./result
     ~~~
 
-- via `cabal v1-build`
-
-    ~~~~.sh
-    # optionally:
-    # mkdir brittany
-    # cd brittany
-    # cabal sandbox init
-    cabal install brittany --bindir=$HOME/.cabal/bin # -w $PATH_TO_GHC_8_x
-    ~~~~
-
-- via `cabal v2-install`
+- via `cabal`
 
-    ~~~~.sh
-    cabal v2-install brittany
-    ~~~~
+    Due to constant changes to the cabal UI, I have given up on making sure
+    these instructions work before releases. Please do not expect these
+    instructions to be up-to-date; they may produce incomprehensible error
+    messages, they may be broken otherwise, they may work now but break with
+    the next cabal release. Thanks for your understanding, and feel free to
+    open issues for any problems you encounter. -- lennart
 
-- via `cabal v2-build`, should v2-install not work:
+    If you are using cabal-3.0, using
+    `cabal install brittany --installdir=$HOME/.cabal/bin`
+    might work. Keep in mind that cabal merely puts a symlink to the "store"
+    into the installdir, so you have to re-install if you ever clean your
+    store. On cabal-2.4, try `cabal v2-install brittany`. On cabal-2.2 or
+    earlier you might be succesful using
+    ```cabal new-build exe:brittany; cp `find dist-newstyle/ -name brittany -type f | xargs -x ls -t | head -n1` $HOME/.cabal/bin/```.
+    Alternatively, you can also use the v1-approach with sandboxes as
+    `cabal v1-sandbox init; cabal v1-install brittany --bindir=$HOME/.cabal/bin`.
 
-    ~~~~.sh
-    cabal unpack brittany
-    cd brittany-0.11.0.0
-    # cabal new-configure -w $PATH_TO_GHC_8_x
-    cabal new-build exe:brittany
-    # and it should be safe to just copy the executable, e.g.
-    cp `find dist-newstyle/ -name brittany -type f | xargs -x ls -t | head -n1` $HOME/.cabal/bin/
-    ~~~~
+    (TODO: These instructions are more confusing than helpful. I am inclined
+    to just remove them.)
 
 - on ArchLinux via [the brittany AUR package](https://aur.archlinux.org/packages/brittany/)
   using `aura`:
diff --git a/brittany.cabal b/brittany.cabal
--- a/brittany.cabal
+++ b/brittany.cabal
@@ -1,5 +1,5 @@
 name:                 brittany
-version:              0.12.0.0
+version:              0.12.1.0
 synopsis:             Haskell source code formatter
 description: {
   See <https://github.com/lspitzner/brittany/blob/master/README.md the README>.
@@ -39,6 +39,11 @@
   default: False
   manual: True
 
+flag brittany-test-perf
+  description: determines if performance test suite is enabled
+  default: False
+  manual: True
+
 library {
   default-language:
     Haskell2010
@@ -84,10 +89,10 @@
     -fno-warn-redundant-constraints
   }
   build-depends:
-    { base >=4.9 && <4.13
-    , ghc >=8.0.1 && <8.7
+    { base >=4.9 && <4.14
+    , ghc >=8.0.1 && <8.9
     , ghc-paths >=0.1.0.9 && <0.2
-    , ghc-exactprint >=0.5.8 && <0.6.2
+    , ghc-exactprint >=0.5.8 && <0.6.3
     , transformers >=0.5.2.0 && <0.6
     , containers >=0.5.7.1 && <0.7
     , mtl >=2.2.1 && <2.3
@@ -109,10 +114,10 @@
     , unsafe >=0.0 && <0.1
     , safe >=0.3.9 && <0.4
     , deepseq >=1.4.2.0 && <1.5
-    , semigroups >=0.18.2 && <0.19
+    , semigroups >=0.18.2 && <0.20
     , cmdargs >=0.10.14 && <0.11
     , czipwith >=1.0.1.0 && <1.1
-    , ghc-boot-th >=8.0.1 && <8.7
+    , ghc-boot-th >=8.0.1 && <8.9
     , filepath >=1.4.1.0 && <1.5
     , random >= 1.1 && <1.2
     }
@@ -205,7 +210,7 @@
   }
 
 test-suite unittests
-  if flag(brittany-dev-lib) {
+  if flag(brittany-dev-lib) || !flag(brittany-test-perf) {
     buildable: False
   } else {
     buildable: True
diff --git a/src-brittany/Main.hs b/src-brittany/Main.hs
--- a/src-brittany/Main.hs
+++ b/src-brittany/Main.hs
@@ -57,8 +57,7 @@
 
 instance Read WriteMode where
   readPrec = val "display" Display <|> val "inplace" Inplace
-   where
-    val iden v = ReadPrec.lift $ ReadP.string iden >> return v
+    where val iden v = ReadPrec.lift $ ReadP.string iden >> return v
 
 instance Show WriteMode where
   show Display = "display"
@@ -114,7 +113,8 @@
 licenseDoc :: PP.Doc
 licenseDoc = PP.vcat $ List.intersperse
   (PP.text "")
-  [ parDoc $ "Copyright (C) 2016-2017 Lennart Spitzner"
+  [ parDoc $ "Copyright (C) 2016-2019 Lennart Spitzner"
+  , parDoc $ "Copyright (C) 2019 PRODA LTD"
   , parDocW
     [ "This program is free software: you can redistribute it and/or modify"
     , "it under the terms of the GNU Affero General Public License,"
@@ -146,6 +146,7 @@
   printHelp    <- addSimpleBoolFlag "h" ["help"] mempty
   printVersion <- addSimpleBoolFlag "" ["version"] mempty
   printLicense <- addSimpleBoolFlag "" ["license"] mempty
+  noUserConfig <- addSimpleBoolFlag "" ["no-user-config"] mempty
   configPaths  <- addFlagStringParams ""
                                       ["config-file"]
                                       "PATH"
@@ -165,11 +166,11 @@
     "c"
     ["check-mode"]
     (flagHelp
-        (PP.vcat
-          [ PP.text "check for changes but do not write them out"
-          , PP.text "exits with code 0 if no changes necessary, 1 otherwise"
-          ]
-        )
+      (PP.vcat
+        [ PP.text "check for changes but do not write them out"
+        , PP.text "exits with code 0 if no changes necessary, 1 otherwise"
+        ]
+      )
     )
   writeMode <- addFlagReadParam
     ""
@@ -194,7 +195,8 @@
     when printVersion $ do
       do
         putStrLn $ "brittany version " ++ showVersion version
-        putStrLn $ "Copyright (C) 2016-2018 Lennart Spitzner"
+        putStrLn $ "Copyright (C) 2016-2019 Lennart Spitzner"
+        putStrLn $ "Copyright (C) 2019 PRODA LTD"
         putStrLn $ "There is NO WARRANTY, to the extent permitted by law."
       System.Exit.exitSuccess
     when printHelp $ do
@@ -216,7 +218,11 @@
       else pure configPaths
 
     config <-
-      runMaybeT (readConfigsWithUserConfig cmdlineConfig configsToLoad)
+      runMaybeT
+          (if noUserConfig
+            then readConfigs cmdlineConfig configsToLoad
+            else readConfigsWithUserConfig cmdlineConfig configsToLoad
+          )
         >>= \case
               Nothing -> System.Exit.exitWith (System.Exit.ExitFailure 53)
               Just x  -> return x
@@ -224,17 +230,18 @@
       $ trace (showConfigYaml config)
       $ return ()
 
-    results <- zipWithM (coreIO putStrErrLn config (suppressOutput || checkMode))
-                        inputPaths
-                        outputPaths
+    results <- zipWithM
+      (coreIO putStrErrLn config (suppressOutput || checkMode))
+      inputPaths
+      outputPaths
 
     if checkMode
-      then when (any (==Changes) (Data.Either.rights results)) $
-             System.Exit.exitWith (System.Exit.ExitFailure 1)
+      then when (any (== Changes) (Data.Either.rights results))
+        $ System.Exit.exitWith (System.Exit.ExitFailure 1)
       else case results of
-             xs | all Data.Either.isRight xs -> pure ()
-             [Left x] -> System.Exit.exitWith (System.Exit.ExitFailure x)
-             _ -> System.Exit.exitWith (System.Exit.ExitFailure 1)
+        xs | all Data.Either.isRight xs -> pure ()
+        [Left x] -> System.Exit.exitWith (System.Exit.ExitFailure x)
+        _ -> System.Exit.exitWith (System.Exit.ExitFailure 1)
 
 
 data ChangeStatus = Changes | NoChanges
@@ -276,20 +283,19 @@
           viaDebug =
             config & _conf_debug & _dconf_roundtrip_exactprint_only & confUnpack
 
-    let
-      cppCheckFunc dynFlags = if GHC.xopt GHC.Cpp dynFlags
-        then case cppMode of
-          CPPModeAbort -> do
-            return $ Left "Encountered -XCPP. Aborting."
-          CPPModeWarn -> do
-            putErrorLnIO
-              $  "Warning: Encountered -XCPP."
-              ++ " Be warned that -XCPP is not supported and that"
-              ++ " brittany cannot check that its output is syntactically"
-              ++ " valid in its presence."
-            return $ Right True
-          CPPModeNowarn -> return $ Right True
-        else return $ Right False
+    let cppCheckFunc dynFlags = if GHC.xopt GHC.Cpp dynFlags
+          then case cppMode of
+            CPPModeAbort -> do
+              return $ Left "Encountered -XCPP. Aborting."
+            CPPModeWarn -> do
+              putErrorLnIO
+                $  "Warning: Encountered -XCPP."
+                ++ " Be warned that -XCPP is not supported and that"
+                ++ " brittany cannot check that its output is syntactically"
+                ++ " valid in its presence."
+              return $ Right True
+            CPPModeNowarn -> return $ Right True
+          else return $ Right False
     (parseResult, originalContents) <- case inputPathM of
       Nothing -> do
         -- TODO: refactor this hack to not be mixed into parsing logic
@@ -306,7 +312,7 @@
                                                    (hackTransform inputString)
         return (parseRes, Text.pack inputString)
       Just p -> liftIO $ do
-        parseRes <- parseModule ghcOptions p cppCheckFunc
+        parseRes  <- parseModule ghcOptions p cppCheckFunc
         inputText <- Text.IO.readFile p
         -- The above means we read the file twice, but the
         -- GHC API does not really expose the source it
@@ -357,13 +363,12 @@
               let hackF s = fromMaybe s $ TextL.stripPrefix
                     (TextL.pack "-- BRITANY_INCLUDE_HACK ")
                     s
-              let
-                out = TextL.toStrict $ if hackAroundIncludes
-                  then
-                    TextL.intercalate (TextL.pack "\n")
-                    $ fmap hackF
-                    $ TextL.splitOn (TextL.pack "\n") outRaw
-                  else outRaw
+              let out = TextL.toStrict $ if hackAroundIncludes
+                    then
+                      TextL.intercalate (TextL.pack "\n")
+                      $ fmap hackF
+                      $ TextL.splitOn (TextL.pack "\n") outRaw
+                    else outRaw
               out' <- if moduleConf & _conf_obfuscate & confUnpack
                 then lift $ obfuscate out
                 else pure out
diff --git a/src-literatetests/10-tests.blt b/src-literatetests/10-tests.blt
--- a/src-literatetests/10-tests.blt
+++ b/src-literatetests/10-tests.blt
@@ -330,7 +330,16 @@
 #test symbol prefix
 (***) x y = x
 
+#test infix more args simple
+(f >=> g) k = f k >>= g
 
+#test infix more args alignment
+(Left  a <$$> Left  dd) e f = True
+(Left  a <$$> Right d ) e f = True
+(Right a <$$> Left  d ) e f = False
+(Right a <$$> Right dd) e f = True
+
+
 ###############################################################################
 ###############################################################################
 ###############################################################################
@@ -612,7 +621,40 @@
           _ -> True
       ]
 
+###############################################################################
+###############################################################################
+###############################################################################
+#group expression.let
+###############################################################################
+###############################################################################
+###############################################################################
 
+#test single-bind-comment-long
+testMethod foo bar baz qux =
+  let x = undefined foo bar baz qux qux baz bar :: String
+  -- some comment explaining the in expression
+  in  undefined foo x :: String
+
+#test single-bind-comment-short
+testMethod foo bar baz qux =
+  let x = undefined :: String
+  -- some comment explaining the in expression
+  in  undefined :: String
+
+#test single-bind-comment-before
+testMethod foo bar baz qux =
+  -- some comment explaining the in expression
+  let x = undefined :: String in undefined :: String
+
+#test multiple-binds-comment
+foo foo bar baz qux =
+  let a = 1
+      b = 2
+      c = 3
+  -- some comment explaining the in expression
+  in  undefined :: String
+
+
 ###############################################################################
 ###############################################################################
 ###############################################################################
@@ -1065,6 +1107,13 @@
 instance MyClass Int where
   myMethod x = x + 1
 
+#test simple-method-comment
+
+instance MyClass Int where
+  myMethod x =
+    -- insightful comment
+    x + 1
+
 #test simple-method-signature
 
 instance MyClass Int where
@@ -1213,6 +1262,7 @@
 type instance MyFam (Maybe a) = a -> Bool
 
 #test simple-typefam-instance-parens
+#pending the parens cause problems since ghc-8.8
 
 type instance (MyFam (String -> Int)) = String
 
@@ -1230,6 +1280,7 @@
   = AnotherType -- Here's another
 
 #test simple-typefam-instance-parens-comment
+#pending the parens cause problems since ghc-8.8
 
 -- | A happy family
 type instance (MyFam Bool) -- This is an odd one
diff --git a/src-literatetests/14-extensions.blt b/src-literatetests/14-extensions.blt
--- a/src-literatetests/14-extensions.blt
+++ b/src-literatetests/14-extensions.blt
@@ -130,3 +130,29 @@
   hello
   |]
   pure True
+
+###############################################################################
+## OverloadedLabels
+#test bare label
+{-# LANGUAGE OverloadedLabels #-}
+foo = #bar
+
+#test applied and composed label
+{-# LANGUAGE OverloadedLabels #-}
+foo = #bar . #baz $ fmap #foo xs
+
+###############################################################################
+## ImplicitParams
+
+#test IP usage
+{-# LANGUAGE ImplicitParams #-}
+foo = ?bar
+
+#test IP binding
+{-# LANGUAGE ImplicitParams #-}
+foo = let ?bar = Foo in value
+
+#test IP type signature
+{-# LANGUAGE ImplicitParams #-}
+foo :: (?bar::Bool) => ()
+foo = ()
diff --git a/src-literatetests/15-regressions.blt b/src-literatetests/15-regressions.blt
--- a/src-literatetests/15-regressions.blt
+++ b/src-literatetests/15-regressions.blt
@@ -607,7 +607,7 @@
 go _ ((_, IRTypeError ps t1 t2) : _) = Left $ makeError ps t1 t2
 
 #test issue 89 - type-family-instance
-type instance (XPure StageParse) = ()
+type instance XPure StageParse = ()
 type Pair a = (a, a)
 
 #test issue 144
@@ -668,3 +668,15 @@
 
 nor False False = True
 _ `nor` _       = False
+
+#test issue 256 prefix operator match
+
+f ((:) a as) = undefined
+
+#test issue 228 lambda plus lazy or bang pattern
+
+{-# LANGUAGE BangPatterns #-}
+a = \x -> x
+b = \ ~x -> x
+c = \ !x -> x
+d = \(~x) -> x
diff --git a/src-unittests/AsymptoticPerfTests.hs b/src-unittests/AsymptoticPerfTests.hs
--- a/src-unittests/AsymptoticPerfTests.hs
+++ b/src-unittests/AsymptoticPerfTests.hs
@@ -22,7 +22,7 @@
 asymptoticPerfTest :: Spec
 asymptoticPerfTest = do
   it "1000 do statements"
-    $  roundTripEqualWithTimeout 1000000
+    $  roundTripEqualWithTimeout 1500000
     $  (Text.pack "func = do\n")
     <> Text.replicate 1000 (Text.pack "  statement\n")
   it "1000 do nestings"
diff --git a/src/Language/Haskell/Brittany/Internal/Backend.hs b/src/Language/Haskell/Brittany/Internal/Backend.hs
--- a/src/Language/Haskell/Brittany/Internal/Backend.hs
+++ b/src/Language/Haskell/Brittany/Internal/Backend.hs
@@ -173,14 +173,10 @@
         -- layoutResetSepSpace
         priors
           `forM_` \(ExactPrint.Types.Comment comment _ _, ExactPrint.Types.DP (y, x)) ->
-                    do
+                    when (not $ comment == "(" || comment == ")") $ do
                       case comment of
                         ('#':_) -> layoutMoveToCommentPos y (-999)
                                    --  ^ evil hack for CPP
-                        "("     -> pure ()
-                        ")"     -> pure ()
-                                   --  ^ these two fix the formatting of parens
-                                   -- on the lhs of type alias defs
                         _       -> layoutMoveToCommentPos y x
                       -- fixedX <- fixMoveToLineByIsNewline x
                       -- replicateM_ fixedX layoutWriteNewline
@@ -217,7 +213,7 @@
       Nothing -> pure ()
       Just comments -> do
         comments `forM_` \(ExactPrint.Types.Comment comment _ _, ExactPrint.Types.DP (y, x)) ->
-          do
+          when (not $ comment == "(" || comment == ")") $ do
             -- evil hack for CPP:
             case comment of
               ('#':_) -> layoutMoveToCommentPos y (-999)
@@ -251,7 +247,7 @@
       Nothing -> pure ()
       Just comments -> do
         comments `forM_` \(ExactPrint.Types.Comment comment _ _, ExactPrint.Types.DP (y, x)) ->
-          do
+          when (not $ comment == "(" || comment == ")") $ do
             case comment of
               ('#':_) -> layoutMoveToCommentPos y (-999)
                          --  ^ evil hack for CPP
diff --git a/src/Language/Haskell/Brittany/Internal/ExactPrintUtils.hs b/src/Language/Haskell/Brittany/Internal/ExactPrintUtils.hs
--- a/src/Language/Haskell/Brittany/Internal/ExactPrintUtils.hs
+++ b/src/Language/Haskell/Brittany/Internal/ExactPrintUtils.hs
@@ -276,7 +276,10 @@
     Set.singleton
     [ SYB.gmapQi 1 (\t -> ExactPrint.mkAnnKey $ L l t) x
     | locTyCon == SYB.typeRepTyCon (SYB.typeOf x)
-    , l <- SYB.gmapQi 0 SYB.cast x
+    , l :: SrcSpan <- SYB.gmapQi 0 SYB.cast x
+      -- for some reason, ghc-8.8 has forgotten how to infer the type of l,
+      -- even though it is passed to mkAnnKey above, which only accepts
+      -- SrcSpan.
     ]
   )
   ast
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Decl.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Decl.hs
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Decl.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Decl.hs
@@ -20,6 +20,7 @@
 import           Language.Haskell.Brittany.Internal.Types
 import           Language.Haskell.Brittany.Internal.LayouterBasics
 import           Language.Haskell.Brittany.Internal.Config.Types
+import           Language.Haskell.Brittany.Internal.Layouters.Type
 
 import qualified Language.Haskell.GHC.ExactPrint as ExactPrint
 import qualified Language.Haskell.GHC.ExactPrint.Types as ExactPrint
@@ -32,6 +33,7 @@
                                                 , AnnKeywordId(..)
                                                 )
 import           SrcLoc ( SrcSpan, noSrcSpan, Located , getLoc, unLoc )
+import qualified FastString
 import           HsSyn
 #if MIN_VERSION_ghc(8,6,0)
 import           HsExtension (NoExt (..))
@@ -231,6 +233,23 @@
                                                             hasComments
   _ -> Right <$> unknownNodeError "" lbind
 
+layoutIPBind :: ToBriDoc IPBind
+layoutIPBind lipbind@(L _ bind) = case bind of
+#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+  XIPBind{} -> unknownNodeError "XIPBind" lipbind
+  IPBind _ (Right _) _ -> error "brittany internal error: IPBind Right"
+  IPBind _ (Left (L _ (HsIPName name))) expr -> do
+#else
+  IPBind (Right _) _ -> error "brittany internal error: IPBind Right"
+  IPBind (Left (L _ (HsIPName name))) expr -> do
+#endif
+    ipName <- docLit $ Text.pack $ '?' : FastString.unpackFS name
+    binderDoc <- docLit $ Text.pack "="
+    exprDoc <- layoutExpr expr
+    hasComments <- hasAnyCommentsBelow lipbind
+    layoutPatternBindFinal Nothing binderDoc (Just ipName) [([], exprDoc, expr)] Nothing hasComments
+
+
 data BagBindOrSig = BagBind (LHsBindLR GhcPs GhcPs)
                   | BagSig (LSig GhcPs)
 
@@ -268,8 +287,14 @@
     Just . (: []) <$> unknownNodeError "HsValBinds ValBindsOut{}"
                                        (L noSrcSpan x)
 #endif
-  x@(HsIPBinds{}) ->
-    Just . (: []) <$> unknownNodeError "HsIPBinds" (L noSrcSpan x)
+#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+  x@(HsIPBinds _ XHsIPBinds{}) ->
+    Just . (: []) <$> unknownNodeError "XHsIPBinds" (L noSrcSpan x)
+  HsIPBinds _ (IPBinds _ bb) ->
+#else
+  HsIPBinds (IPBinds bb _) ->
+#endif
+    Just <$> mapM layoutIPBind bb
   EmptyLocalBinds{} -> return $ Nothing
 
 -- TODO: we don't need the `LHsExpr GhcPs` anymore, now that there is
@@ -316,11 +341,25 @@
     _ -> pure Nothing
   let mIdStr' = fixPatternBindIdentifier match <$> mIdStr
   patDoc <- docWrapNodePrior lmatch $ case (mIdStr', patDocs) of
-    (Just idStr, p1 : pr) | isInfix -> docCols
-      ColPatternsFuncInfix
-      (  [appSep $ docForceSingleline p1, appSep $ docLit idStr]
-      ++ (spacifyDocs $ docForceSingleline <$> pr)
-      )
+    (Just idStr, p1:p2:pr) | isInfix -> if null pr
+      then
+        docCols ColPatternsFuncInfix
+          [ appSep $ docForceSingleline p1
+          , appSep $ docLit $ idStr
+          , docForceSingleline p2
+          ]
+      else
+        docCols ColPatternsFuncInfix
+          (  [docCols ColPatterns
+               [ docParenL
+               , appSep $ docForceSingleline p1
+               , appSep $ docLit $ idStr
+               , docForceSingleline p2
+               , appSep $ docParenR
+               ]
+             ]
+          ++ (spacifyDocs $ docForceSingleline <$> pr)
+          )
     (Just idStr, []) -> docLit idStr
     (Just idStr, ps) ->
       docCols ColPatternsFuncPrefix
@@ -719,7 +758,7 @@
         let (a : b : rest) = vars
         hasOwnParens <- hasAnnKeywordComment a AnnOpenP
         -- This isn't quite right, but does give syntactically valid results
-        let needsParens = not $ null rest || hasOwnParens
+        let needsParens = not (null rest) || hasOwnParens
         docSeq
           $  [ docLit $ Text.pack "type"
              , docSeparator
@@ -776,24 +815,36 @@
 -- TyFamInstDecl
 --------------------------------------------------------------------------------
 
+
+
 layoutTyFamInstDecl :: Bool -> ToBriDoc TyFamInstDecl
 layoutTyFamInstDecl inClass (L loc tfid) = do
   let
-#if MIN_VERSION_ghc(8,6,0)
+#if MIN_VERSION_ghc(8,8,0)
     linst = L loc (TyFamInstD NoExt tfid)
+    feqn@(FamEqn _ name bndrsMay pats _fixity typ) = hsib_body $ tfid_eqn tfid
+    -- bndrsMay isJust e.g. with
+    --   type instance forall a . MyType (Maybe a) = Either () a
+    lfeqn = L loc feqn
+#elif MIN_VERSION_ghc(8,6,0)
+    linst = L loc (TyFamInstD NoExt tfid)
     feqn@(FamEqn _ name pats _fixity typ) = hsib_body $ tfid_eqn tfid
+    bndrsMay = Nothing
     lfeqn = L loc feqn
 #elif MIN_VERSION_ghc(8,4,0)
     linst = L loc (TyFamInstD tfid)
     feqn@(FamEqn name pats _fixity typ) = hsib_body $ tfid_eqn tfid
+    bndrsMay = Nothing
     lfeqn = L loc feqn
 #elif MIN_VERSION_ghc(8,2,0)
     linst = L loc (TyFamInstD tfid)
     lfeqn@(L _ (TyFamEqn name boundPats _fixity typ)) = tfid_eqn tfid
+    bndrsMay = Nothing
     pats = hsib_body boundPats
 #else
     linst = L loc (TyFamInstD tfid)
     lfeqn@(L _ (TyFamEqn name boundPats typ)) = tfid_eqn tfid
+    bndrsMay = Nothing
     pats = hsib_body boundPats
 #endif
   docWrapNodePrior linst $ do
@@ -804,15 +855,23 @@
         then docLit $ Text.pack "type"
         else docSeq
           [appSep . docLit $ Text.pack "type", docLit $ Text.pack "instance"]
+      makeForallDoc :: [LHsTyVarBndr GhcPs] -> ToBriDocM BriDocNumbered
+      makeForallDoc bndrs = do
+        bndrDocs <- layoutTyVarBndrs bndrs
+        docSeq
+          (  [docLit (Text.pack "forall")]
+          ++ processTyVarBndrsSingleline bndrDocs
+          )
       lhs =
         docWrapNode lfeqn
           .  appSep
           .  docWrapNodeRest linst
           .  docSeq
-          $  (appSep instanceDoc :)
-          $  [ docParenL | needsParens ]
+          $  [appSep instanceDoc]
+          ++ [ makeForallDoc foralls | Just foralls <- [bndrsMay] ]
+          ++ [ docParenL | needsParens ]
           ++ [appSep $ docWrapNode name $ docLit nameStr]
-          ++ intersperse docSeparator (layoutType <$> pats)
+          ++ intersperse docSeparator (layoutHsTyPats pats)
           ++ [ docParenR | needsParens ]
     hasComments <- (||)
       <$> hasAnyRegularCommentsConnected lfeqn
@@ -821,6 +880,20 @@
     layoutLhsAndType hasComments lhs "=" typeDoc
 
 
+#if MIN_VERSION_ghc(8,8,0)
+layoutHsTyPats :: [HsArg (LHsType GhcPs) (LHsKind GhcPs)] -> [ToBriDocM BriDocNumbered]
+layoutHsTyPats pats = pats <&> \case
+  HsValArg tm     -> layoutType tm
+  HsTypeArg _l ty -> docSeq [docLit $ Text.pack "@", layoutType ty]
+    -- we ignore the SourceLoc here.. this LPat not being (L _ Pat{}) change
+    -- is a bit strange. Hopefully this does not ignore any important
+    -- annotations.
+  HsArgPar _l     -> error "brittany internal error: HsArgPar{}"
+#else
+layoutHsTyPats :: [LHsType GhcPs] -> [ToBriDocM BriDocNumbered]
+layoutHsTyPats pats = layoutType <$> pats
+#endif
+
 --------------------------------------------------------------------------------
 -- ClsInstDecl
 --------------------------------------------------------------------------------
@@ -834,6 +907,7 @@
 layoutClsInst lcid@(L _ cid) = docLines
   [ layoutInstanceHead
   , docEnsureIndent BrIndentRegular
+  $  docSetIndentLevel
   $  docSortedLines
   $  fmap layoutAndLocateSig          (cid_sigs cid)
   ++ fmap layoutAndLocateBind         (bagToList $ cid_binds cid)
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Expr.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Expr.hs
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Expr.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Expr.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DataKinds #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Brittany.Internal.Layouters.Expr
   ( layoutExpr
@@ -55,13 +56,23 @@
     HsRecFld{} -> do
       -- TODO
       briDocByExactInlineOnly "HsRecFld" lexpr
-    HsOverLabel{} -> do
-      -- TODO
-      briDocByExactInlineOnly "HsOverLabel{}" lexpr
-    HsIPVar{} -> do
-      -- TODO
-      briDocByExactInlineOnly "HsOverLabel{}" lexpr
 #if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+    HsOverLabel _ext _reboundFromLabel name ->
+#elif MIN_VERSION_ghc(8,2,0) /* ghc-8.2 8.4 */
+    HsOverLabel _reboundFromLabel name ->
+#else                        /* ghc-8.0 */
+    HsOverLabel name ->
+#endif
+      let label = FastString.unpackFS name
+      in docLit . Text.pack $ '#' : label
+#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+    HsIPVar _ext (HsIPName name) ->
+#else
+    HsIPVar (HsIPName name) ->
+#endif
+      let label = FastString.unpackFS name
+      in docLit . Text.pack $ '?' : label
+#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
     HsOverLit _ olit -> do
 #else
     HsOverLit olit -> do
@@ -91,7 +102,27 @@
       ,  L _ (GRHS [] body)     <- lgrhs
 #endif
       -> do
-      patDocs <- pats `forM` \p -> fmap return $ colsWrapPat =<< layoutPat p
+      patDocs <- zip (True : repeat False) pats `forM` \(isFirst, p) ->
+        fmap return $ do
+          -- this code could be as simple as `colsWrapPat =<< layoutPat p`
+          -- if it was not for the following two cases:
+          -- \ !x -> x
+          -- \ ~x -> x
+          -- These make it necessary to special-case an additional separator.
+          -- (TODO: we create a BDCols here, but then make it ineffective
+          -- by wrapping it in docSeq below. We _could_ add alignments for
+          -- stuff like lists-of-lambdas. Nothing terribly important..)
+          let shouldPrefixSeparator = case p of
+                (ghcDL -> L _ LazyPat{}) -> isFirst
+                (ghcDL -> L _ BangPat{}) -> isFirst
+                _               -> False
+          patDocSeq <- layoutPat p
+          fixed <- case Seq.viewl patDocSeq of
+            p1 Seq.:< pr | shouldPrefixSeparator -> do
+              p1' <- docSeq [docSeparator, pure p1]
+              pure (p1' Seq.<| pr)
+            _ -> pure patDocSeq
+          colsWrapPat fixed
       bodyDoc <- docAddBaseY BrIndentRegular <$> docSharedWrapper layoutExpr body
       let funcPatternPartLine =
             docCols ColCasePattern
@@ -268,7 +299,11 @@
           expDoc1
           expDoc2
         ]
-#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+#if MIN_VERSION_ghc(8,8,0)   /* ghc-8.8 */
+    HsAppType _ _ XHsWildCardBndrs{} ->
+      error "brittany internal error: HsAppType XHsWildCardBndrs"
+    HsAppType _ exp1 (HsWC _ ty1) -> do
+#elif MIN_VERSION_ghc(8,6,0) /* ghc-8.6 */
     HsAppType XHsWildCardBndrs{} _ ->
       error "brittany internal error: HsAppType XHsWildCardBndrs"
     HsAppType (HsWC _ ty1) exp1 -> do
@@ -711,10 +746,10 @@
 #else
     HsLet binds exp1 -> do
 #endif
-      expDoc1   <- docSharedWrapper layoutExpr exp1
+      expDoc1     <- docSharedWrapper layoutExpr exp1
       -- We jump through some ugly hoops here to ensure proper sharing.
-      mBindDocs <- mapM (fmap (fmap return) . docWrapNodeRest lexpr . return)
-               =<< layoutLocalBinds binds
+      hasComments <- hasAnyCommentsBelow lexpr
+      mBindDocs   <- fmap (fmap (fmap pure)) $ layoutLocalBinds binds
       let
         ifIndentFreeElse :: a -> a -> a
         ifIndentFreeElse x y =
@@ -731,37 +766,38 @@
       -- if "let" is moved horizontally as part of the transformation, as the
       -- comments before the first let item are moved horizontally with it.
       docSetBaseAndIndent $ case mBindDocs of
-        Just [bindDoc] -> docAlt
-          [ docSeq
-              [ appSep $ docLit $ Text.pack "let"
-              , appSep $ docForceSingleline bindDoc
-              , appSep $ docLit $ Text.pack "in"
-              , docForceSingleline expDoc1
-              ]
-          , docLines
-              [ docAlt
-                  [ docSeq
-                      [ appSep $ docLit $ Text.pack "let"
-                      , ifIndentFreeElse docSetBaseAndIndent docForceSingleline
-                      $ bindDoc
-                      ]
-                  , docAddBaseY BrIndentRegular
-                  $ docPar
-                    (docLit $ Text.pack "let")
-                    (docSetBaseAndIndent bindDoc)
-                  ]
-              , docAlt
-                  [ docSeq
-                      [ appSep $ docLit $ Text.pack $ ifIndentFreeElse "in " "in"
-                      , ifIndentFreeElse docSetBaseAndIndent docForceSingleline expDoc1
-                      ]
-                  , docAddBaseY BrIndentRegular
-                  $ docPar
-                    (docLit $ Text.pack "in")
-                    (docSetBaseY expDoc1)
-                  ]
-              ]
-          ]
+        Just [bindDoc] -> runFilteredAlternative $ do
+          addAlternativeCond (not hasComments) $ docSeq
+            [ appSep $ docLit $ Text.pack "let"
+            , docNodeAnnKW lexpr (Just AnnLet)
+            $ appSep $ docForceSingleline bindDoc
+            , appSep $ docLit $ Text.pack "in"
+            , docForceSingleline expDoc1
+            ]
+          addAlternative $ docLines
+            [ docNodeAnnKW lexpr (Just AnnLet)
+            $ docAlt
+                [ docSeq
+                    [ appSep $ docLit $ Text.pack "let"
+                    , ifIndentFreeElse docSetBaseAndIndent docForceSingleline
+                    $ bindDoc
+                    ]
+                , docAddBaseY BrIndentRegular
+                $ docPar
+                  (docLit $ Text.pack "let")
+                  (docSetBaseAndIndent bindDoc)
+                ]
+            , docAlt
+                [ docSeq
+                    [ appSep $ docLit $ Text.pack $ ifIndentFreeElse "in " "in"
+                    , ifIndentFreeElse docSetBaseAndIndent docForceSingleline expDoc1
+                    ]
+                , docAddBaseY BrIndentRegular
+                $ docPar
+                  (docLit $ Text.pack "in")
+                  (docSetBaseY expDoc1)
+                ]
+            ]
         Just bindDocs@(_:_) -> runFilteredAlternative $ do
           --either
           --  let
@@ -791,7 +827,8 @@
             IndentPolicyLeft     -> docLines noHangingBinds
             IndentPolicyMultiple -> docLines noHangingBinds
             IndentPolicyFree     -> docLines
-              [ docSeq
+              [ docNodeAnnKW lexpr (Just AnnLet)
+              $ docSeq
                 [ appSep $ docLit $ Text.pack "let"
                 , docSetBaseAndIndent $ docLines bindDocs
                 ]
@@ -802,7 +839,8 @@
               ]
           addAlternative
             $ docLines
-            [ docAddBaseY BrIndentRegular
+            [ docNodeAnnKW lexpr (Just AnnLet)
+            $ docAddBaseY BrIndentRegular
             $ docPar
               (docLit $ Text.pack "let")
               (docSetBaseAndIndent $ docLines $ bindDocs)
@@ -1024,7 +1062,13 @@
             Ambiguous   n _ -> (lfield, lrdrNameToText n, rFExpDoc)
 #endif
       recordExpression indentPolicy lexpr rExprDoc rFs
-#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+#if MIN_VERSION_ghc(8,8,0)   /* ghc-8.6 */
+    ExprWithTySig _ _ (HsWC _ XHsImplicitBndrs{}) ->
+      error "brittany internal error: ExprWithTySig HsWC XHsImplicitBndrs"
+    ExprWithTySig _ _ XHsWildCardBndrs{} ->
+      error "brittany internal error: ExprWithTySig XHsWildCardBndrs"
+    ExprWithTySig _ exp1 (HsWC _ (HsIB _ typ1)) -> do
+#elif MIN_VERSION_ghc(8,6,0) /* ghc-8.6 */
     ExprWithTySig (HsWC _ XHsImplicitBndrs{}) _ ->
       error "brittany internal error: ExprWithTySig HsWC XHsImplicitBndrs"
     ExprWithTySig XHsWildCardBndrs{} _ ->
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Pattern.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Pattern.hs
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Pattern.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Pattern.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DataKinds #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Brittany.Internal.Layouters.Pattern
   ( layoutPat
@@ -13,7 +14,13 @@
 import           Language.Haskell.Brittany.Internal.Types
 import           Language.Haskell.Brittany.Internal.LayouterBasics
 
-import           GHC ( Located, runGhc, GenLocated(L), moduleNameString, ol_val )
+import           GHC                            ( Located
+                                                , runGhc
+                                                , GenLocated(L)
+                                                , moduleNameString
+                                                , ol_val
+                                                )
+import qualified GHC
 import           HsSyn
 import           Name
 import           BasicTypes
@@ -33,8 +40,8 @@
 --        ^^^^^^^^^^ this part
 -- We will use `case .. of` as the imagined prefix to the examples used in
 -- the different cases below.
-layoutPat :: ToBriDocC (Pat GhcPs) (Seq BriDocNumbered)
-layoutPat lpat@(L _ pat) = docWrapNode lpat $ case pat of
+layoutPat :: LPat GhcPs -> ToBriDocM (Seq BriDocNumbered)
+layoutPat (ghcDL -> lpat@(L _ pat)) = docWrapNode lpat $ case pat of
   WildPat _  -> fmap Seq.singleton $ docLit $ Text.pack "_"
     -- _ -> expr
 #if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
@@ -51,8 +58,10 @@
 #endif
     fmap Seq.singleton $ allocateNode $ litBriDoc lit
     -- 0 -> expr
-#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+#if MIN_VERSION_ghc(8,8,0)   /* ghc-8.8 */
   ParPat _ inner -> do
+#elif MIN_VERSION_ghc(8,6,0) /* ghc-8.6 */
+  ParPat _ inner -> do
 #else                        /* ghc-8.0 8.2 8.4 */
   ParPat inner -> do
 #endif
@@ -77,7 +86,7 @@
     --       return $ (x1' Seq.<| middle) Seq.|> xN'
   ConPatIn lname (PrefixCon args) -> do
     -- Abc a b c -> expr
-    let nameDoc = lrdrNameToText lname
+    nameDoc <- lrdrNameToTextAnn lname
     argDocs <- layoutPat `mapM` args
     if null argDocs
       then return <$> docLit nameDoc
@@ -177,7 +186,9 @@
 #endif
     -- bind@nestedpat -> expr
     wrapPatPrepend asPat (docLit $ lrdrNameToText asName <> Text.pack "@")
-#if MIN_VERSION_ghc(8,6,0)   /* ghc-8.6 */
+#if MIN_VERSION_ghc(8,8,0)   /* ghc-8.8 */
+  SigPat _ pat1 (HsWC _ (HsIB _ ty1)) -> do
+#elif MIN_VERSION_ghc(8,6,0) /* ghc-8.6 */
   SigPat (HsWC _ (HsIB _ ty1)) pat1 -> do
 #elif MIN_VERSION_ghc(8,2,0) /* ghc-8.2 8.4 */
   SigPatIn pat1 (HsWC _ (HsIB _ ty1 _)) -> do
@@ -242,13 +253,13 @@
 -- else
 --   VarPat n -> return $ stringLayouter lpat $ rdrNameToText n
 -- endif
-  _ -> return <$> briDocByExactInlineOnly "some unknown pattern" lpat
+  _ -> return <$> briDocByExactInlineOnly "some unknown pattern" (ghcDL lpat)
 
 colsWrapPat :: Seq BriDocNumbered -> ToBriDocM BriDocNumbered
 colsWrapPat = docCols ColPatterns . fmap return . Foldable.toList
 
 wrapPatPrepend
-  :: Located (Pat GhcPs)
+  :: LPat GhcPs
   -> ToBriDocM BriDocNumbered
   -> ToBriDocM (Seq BriDocNumbered)
 wrapPatPrepend pat prepElem = do
@@ -260,7 +271,7 @@
       return $ x1' Seq.<| xR
 
 wrapPatListy
-  :: [Located (Pat GhcPs)]
+  :: [LPat GhcPs]
   -> String
   -> ToBriDocM BriDocNumbered
   -> ToBriDocM BriDocNumbered
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Type.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Type.hs
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Type.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Type.hs
@@ -2,6 +2,8 @@
 
 module Language.Haskell.Brittany.Internal.Layouters.Type
   ( layoutType
+  , layoutTyVarBndrs
+  , processTyVarBndrsSingleline
   )
 where
 
@@ -32,21 +34,19 @@
 layoutType :: ToBriDoc HsType
 layoutType ltype@(L _ typ) = docWrapNode ltype $ case typ of
   -- _ | traceShow (ExactPrint.Types.mkAnnKey ltype) False -> error "impossible"
+#if MIN_VERSION_ghc(8,2,0)
 #if MIN_VERSION_ghc(8,6,0)
   HsTyVar _ promoted name -> do
-    t <- lrdrNameToTextAnn name
-    case promoted of
-      Promoted -> docSeq
-        [ docSeparator
-        , docTick
-        , docWrapNode name $ docLit t
-        ]
-      NotPromoted -> docWrapNode name $ docLit t
-#elif MIN_VERSION_ghc(8,2,0) /* ghc-8.2 */
+#else   /* ghc-8.2 ghc-8.4 */
   HsTyVar promoted name -> do
+#endif
     t <- lrdrNameToTextAnn name
     case promoted of
+#if MIN_VERSION_ghc(8,8,0)
+      IsPromoted -> docSeq
+#else /* ghc-8.2 8.4 8.6 */
       Promoted -> docSeq
+#endif
         [ docSeparator
         , docTick
         , docWrapNode name $ docLit t
@@ -63,32 +63,13 @@
   HsForAllTy bndrs (L _ (HsQualTy (L _ cntxts) typ2)) -> do
 #endif
     typeDoc <- docSharedWrapper layoutType typ2
-    tyVarDocs <- bndrs `forM` \case
-#if MIN_VERSION_ghc(8,6,0)
-      (L _ (UserTyVar _ name)) -> return $ (lrdrNameToText name, Nothing)
-      (L _ (KindedTyVar _ lrdrName kind)) -> do
-        d <- docSharedWrapper layoutType kind
-        return $ (lrdrNameToText lrdrName, Just $ d)
-      (L _ (XTyVarBndr{})) -> error "brittany internal error: XTyVarBndr"
-#else
-      (L _ (UserTyVar name)) -> return $ (lrdrNameToText name, Nothing)
-      (L _ (KindedTyVar lrdrName kind)) -> do
-        d <- docSharedWrapper layoutType kind
-        return $ (lrdrNameToText lrdrName, Just $ d)
-#endif
+    tyVarDocs <- layoutTyVarBndrs bndrs
     cntxtDocs <- cntxts `forM` docSharedWrapper layoutType
     let maybeForceML = case typ2 of
           (L _ HsFunTy{}) -> docForceMultiline
           _               -> id
     let
-      tyVarDocLineList = tyVarDocs >>= \case
-        (tname, Nothing) -> [docLit $ Text.pack " " <> tname]
-        (tname, Just doc) -> [ docLit $ Text.pack " ("
-                                    <> tname
-                                    <> Text.pack " :: "
-                             , docForceSingleline $ doc
-                             , docLit $ Text.pack ")"
-                             ]
+      tyVarDocLineList = processTyVarBndrsSingleline tyVarDocs
       forallDoc = docAlt
         [ let
             open = docLit $ Text.pack "forall"
@@ -142,7 +123,7 @@
             else let
               open = docLit $ Text.pack "forall"
               close = docLit $ Text.pack " . "
-              in docSeq ([open]++tyVarDocLineList++[close])
+              in docSeq ([open, docSeparator]++tyVarDocLineList++[close])
         , docForceSingleline contextDoc
         , docLit $ Text.pack " => "
         , docForceSingleline typeDoc
@@ -172,31 +153,11 @@
   HsForAllTy bndrs typ2 -> do
 #endif
     typeDoc <- layoutType typ2
-    tyVarDocs <- bndrs `forM` \case
-#if MIN_VERSION_ghc(8,6,0)
-      (L _ (UserTyVar _ name)) -> return $ (lrdrNameToText name, Nothing)
-      (L _ (KindedTyVar _ lrdrName kind)) -> do
-        d <- layoutType kind
-        return $ (lrdrNameToText lrdrName, Just $ return d)
-      (L _ (XTyVarBndr{})) -> error "brittany internal error: XTyVarBndr"
-#else
-      (L _ (UserTyVar name)) -> return $ (lrdrNameToText name, Nothing)
-      (L _ (KindedTyVar lrdrName kind)) -> do
-        d <- layoutType kind
-        return $ (lrdrNameToText lrdrName, Just $ return d)
-#endif
+    tyVarDocs <- layoutTyVarBndrs bndrs
     let maybeForceML = case typ2 of
           (L _ HsFunTy{}) -> docForceMultiline
           _               -> id
-    let
-      tyVarDocLineList = tyVarDocs >>= \case
-        (tname, Nothing) -> [docLit $ Text.pack " " <> tname]
-        (tname, Just doc) -> [ docLit $ Text.pack " ("
-                                    <> tname
-                                    <> Text.pack " :: "
-                             , docForceSingleline doc
-                             , docLit $ Text.pack ")"
-                             ]
+    let tyVarDocLineList = processTyVarBndrsSingleline tyVarDocs
     docAlt
       -- forall x . x
       [ docSeq
@@ -771,3 +732,46 @@
       else docLit $ Text.pack "*"
   XHsType{} -> error "brittany internal error: XHsType"
 #endif
+#if MIN_VERSION_ghc(8,8,0)
+  HsAppKindTy _ ty kind -> do
+    t <- docSharedWrapper layoutType ty
+    k <- docSharedWrapper layoutType kind
+    docAlt
+      [ docSeq
+          [ docForceSingleline t
+          , docSeparator
+          , docLit $ Text.pack "@"
+          , docForceSingleline k
+          ]
+      , docPar
+          t
+          (docSeq [docLit $ Text.pack "@", k ])
+      ]
+#endif
+
+layoutTyVarBndrs
+  :: [LHsTyVarBndr GhcPs]
+  -> ToBriDocM [(Text, Maybe (ToBriDocM BriDocNumbered))]
+layoutTyVarBndrs = mapM $ \case
+#if MIN_VERSION_ghc(8,6,0)
+  (L _ (UserTyVar _ name)) -> return $ (lrdrNameToText name, Nothing)
+  (L _ (KindedTyVar _ lrdrName kind)) -> do
+    d <- docSharedWrapper layoutType kind
+    return $ (lrdrNameToText lrdrName, Just $ d)
+  (L _ (XTyVarBndr{})) -> error "brittany internal error: XTyVarBndr"
+#else
+  (L _ (UserTyVar name)) -> return $ (lrdrNameToText name, Nothing)
+  (L _ (KindedTyVar lrdrName kind)) -> do
+    d <- docSharedWrapper layoutType kind
+    return $ (lrdrNameToText lrdrName, Just $ d)
+#endif
+
+processTyVarBndrsSingleline
+  :: [(Text, Maybe (ToBriDocM BriDocNumbered))] -> [ToBriDocM BriDocNumbered]
+processTyVarBndrsSingleline bndrDocs = bndrDocs >>= \case
+  (tname, Nothing) -> [docLit $ Text.pack " " <> tname]
+  (tname, Just doc) ->
+    [ docLit $ Text.pack " (" <> tname <> Text.pack " :: "
+    , docForceSingleline $ doc
+    , docLit $ Text.pack ")"
+    ]
diff --git a/src/Language/Haskell/Brittany/Internal/Prelude.hs b/src/Language/Haskell/Brittany/Internal/Prelude.hs
--- a/src/Language/Haskell/Brittany/Internal/Prelude.hs
+++ b/src/Language/Haskell/Brittany/Internal/Prelude.hs
@@ -18,7 +18,10 @@
 #endif
 
 import RdrName                        as E ( RdrName )
-
+#if MIN_VERSION_ghc(8,8,0)
+import qualified GHC                       ( dL, HasSrcSpan, SrcSpanLess )
+#endif
+import qualified GHC                       ( Located )
 
 
 -- more general:
@@ -409,4 +412,13 @@
 type instance IdP GhcPs = RdrName
 
 type GhcPs = RdrName
+#endif
+
+
+#if MIN_VERSION_ghc(8,8,0)
+ghcDL :: GHC.HasSrcSpan a => a -> GHC.Located (GHC.SrcSpanLess a)
+ghcDL = GHC.dL
+#else              /* ghc-8.0 8.2 8.4 8.6 */
+ghcDL :: GHC.Located a -> GHC.Located a
+ghcDL x = x
 #endif
