diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs
index dee1a9977570f85a905c805dc630cc0bb9b9906a..86aac8d99d9145faa4de74c105bbc06d042b718c 100644
--- a/compiler/GHC/Tc/Errors/Ppr.hs
+++ b/compiler/GHC/Tc/Errors/Ppr.hs
@@ -21,6 +21,8 @@ module GHC.Tc.Errors.Ppr
 import GHC.Prelude
 
 import GHC.Builtin.Names
+import GHC.Builtin.Types (boxedRepDataConTyCon)
+import GHC.Builtin.Types.Prim (tYPETyCon)
 
 import GHC.Core.Coercion
 import GHC.Core.Unify     ( tcMatchTys )
@@ -802,6 +804,100 @@ instance Diagnostic TcRnMessage where
     TcRnInvalidCIdentifier target
       -> mkSimpleDecorated $
            sep [quotes (ppr target) <+> text "is not a valid C identifier"]
+    TcRnExpectedValueId thing
+      -> mkSimpleDecorated $
+           ppr thing <+> text "used where a value identifier was expected"
+    TcRnNotARecordSelector field
+      -> mkSimpleDecorated $
+           hsep [quotes (ppr field), text "is not a record selector"]
+    TcRnRecSelectorEscapedTyVar lbl
+      -> mkSimpleDecorated $
+           text "Cannot use record selector" <+> quotes (ppr lbl) <+>
+           text "as a function due to escaped type variables"
+    TcRnPatSynNotBidirectional name
+      -> mkSimpleDecorated $
+           text "non-bidirectional pattern synonym"
+           <+> quotes (ppr name) <+> text "used in an expression"
+    TcRnSplicePolymorphicLocalVar ident
+      -> mkSimpleDecorated $
+           text "Can't splice the polymorphic local variable" <+> quotes (ppr ident)
+    TcRnIllegalDerivingItem hs_ty
+      -> mkSimpleDecorated $
+           text "Illegal deriving item" <+> quotes (ppr hs_ty)
+    TcRnUnexpectedAnnotation ty bang
+      -> mkSimpleDecorated $
+           let err = case bang of
+                 HsSrcBang _ SrcUnpack _           -> "UNPACK"
+                 HsSrcBang _ SrcNoUnpack _         -> "NOUNPACK"
+                 HsSrcBang _ NoSrcUnpack SrcLazy   -> "laziness"
+                 HsSrcBang _ _ _                   -> "strictness"
+            in text "Unexpected" <+> text err <+> text "annotation:" <+> ppr ty $$
+               text err <+> text "annotation cannot appear nested inside a type"
+    TcRnIllegalRecordSyntax ty
+      -> mkSimpleDecorated $
+           text "Record syntax is illegal here:" <+> ppr ty
+    TcRnUnexpectedTypeSplice ty
+      -> mkSimpleDecorated $
+           text "Unexpected type splice:" <+> ppr ty
+    TcRnInvalidVisibleKindArgument arg ty
+      -> mkSimpleDecorated $
+           text "Cannot apply function of kind" <+> quotes (ppr ty)
+             $$ text "to visible kind argument" <+> quotes (ppr arg)
+    TcRnTooManyBinders ki bndrs
+      -> mkSimpleDecorated $
+           hang (text "Not a function kind:")
+              4 (ppr ki) $$
+           hang (text "but extra binders found:")
+              4 (fsep (map ppr bndrs))
+    TcRnDifferentNamesForTyVar n1 n2
+      -> mkSimpleDecorated $
+           hang (text "Different names for the same type variable:") 2 info
+         where
+           info | nameOccName n1 /= nameOccName n2
+                = quotes (ppr n1) <+> text "and" <+> quotes (ppr n2)
+                | otherwise -- Same OccNames! See C2 in
+                            -- Note [Swizzling the tyvars before generaliseTcTyCon]
+                = vcat [ quotes (ppr n1) <+> text "bound at" <+> ppr (getSrcLoc n1)
+                       , quotes (ppr n2) <+> text "bound at" <+> ppr (getSrcLoc n2) ]
+    TcRnInvalidReturnKind data_sort allowed_kind kind _suggested_ext
+      -> mkSimpleDecorated $
+           sep [ ppDataSort data_sort <+>
+                 text "has non-" <>
+                 allowed_kind_tycon
+               , (if is_data_family then text "and non-variable" else empty) <+>
+                 text "return kind" <+> quotes (ppr kind)
+               ]
+         where
+          is_data_family =
+            case data_sort of
+              DataDeclSort{}     -> False
+              DataInstanceSort{} -> False
+              DataFamilySort     -> True
+          allowed_kind_tycon =
+            case allowed_kind of
+              AnyTYPEKind  -> ppr tYPETyCon
+              AnyBoxedKind -> ppr boxedRepDataConTyCon
+              LiftedKind   -> ppr liftedTypeKind
+    TcRnClassKindNotConstraint _kind
+      -> mkSimpleDecorated $
+           text "Kind signature on a class must end with" <+> ppr constraintKind $$
+           text "unobscured by type families"
+    TcRnUnpromotableThing name err
+      -> mkSimpleDecorated $
+           (hang (pprPECategory err <+> quotes (ppr name) <+> text "cannot be used here")
+                        2 (parens reason))
+        where
+          reason = case err of
+                     ConstrainedDataConPE pred
+                                    -> text "it has an unpromotable context"
+                                       <+> quotes (ppr pred)
+                     FamDataConPE   -> text "it comes from a data family instance"
+                     NoDataKindsDC  -> text "perhaps you intended to use DataKinds"
+                     PatSynPE       -> text "pattern synonyms cannot be promoted"
+                     RecDataConPE   -> same_rec_group_msg
+                     ClassPE        -> same_rec_group_msg
+                     TyConPE        -> same_rec_group_msg
+          same_rec_group_msg = text "it is defined and used in the same recursive group"
 
   diagnosticReason = \case
     TcRnUnknownMessage m
@@ -1062,6 +1158,36 @@ instance Diagnostic TcRnMessage where
       -> ErrorWithoutFlag
     TcRnInvalidCIdentifier{}
       -> ErrorWithoutFlag
+    TcRnExpectedValueId{}
+      -> ErrorWithoutFlag
+    TcRnNotARecordSelector{}
+      -> ErrorWithoutFlag
+    TcRnRecSelectorEscapedTyVar{}
+      -> ErrorWithoutFlag
+    TcRnPatSynNotBidirectional{}
+      -> ErrorWithoutFlag
+    TcRnSplicePolymorphicLocalVar{}
+      -> ErrorWithoutFlag
+    TcRnIllegalDerivingItem{}
+      -> ErrorWithoutFlag
+    TcRnUnexpectedAnnotation{}
+      -> ErrorWithoutFlag
+    TcRnIllegalRecordSyntax{}
+      -> ErrorWithoutFlag
+    TcRnUnexpectedTypeSplice{}
+      -> ErrorWithoutFlag
+    TcRnInvalidVisibleKindArgument{}
+      -> ErrorWithoutFlag
+    TcRnTooManyBinders{}
+      -> ErrorWithoutFlag
+    TcRnDifferentNamesForTyVar{}
+      -> ErrorWithoutFlag
+    TcRnInvalidReturnKind{}
+      -> ErrorWithoutFlag
+    TcRnClassKindNotConstraint{}
+      -> ErrorWithoutFlag
+    TcRnUnpromotableThing{}
+      -> ErrorWithoutFlag
 
   diagnosticHints = \case
     TcRnUnknownMessage m
@@ -1321,6 +1447,39 @@ instance Diagnostic TcRnMessage where
            _ -> noHints
     TcRnInvalidCIdentifier{}
       -> noHints
+    TcRnExpectedValueId{}
+      -> noHints
+    TcRnNotARecordSelector{}
+      -> noHints
+    TcRnRecSelectorEscapedTyVar{}
+      -> [SuggestPatternMatchingSyntax]
+    TcRnPatSynNotBidirectional{}
+      -> noHints
+    TcRnSplicePolymorphicLocalVar{}
+      -> noHints
+    TcRnIllegalDerivingItem{}
+      -> noHints
+    TcRnUnexpectedAnnotation{}
+      -> noHints
+    TcRnIllegalRecordSyntax{}
+      -> noHints
+    TcRnUnexpectedTypeSplice{}
+      -> noHints
+    TcRnInvalidVisibleKindArgument{}
+      -> noHints
+    TcRnTooManyBinders{}
+      -> noHints
+    TcRnDifferentNamesForTyVar{}
+      -> noHints
+    TcRnInvalidReturnKind _ _ _ mb_suggest_unlifted_ext
+      -> case mb_suggest_unlifted_ext of
+           Nothing -> noHints
+           Just SuggestUnliftedNewtypes -> [suggestExtension LangExt.UnliftedNewtypes]
+           Just SuggestUnliftedDatatypes -> [suggestExtension LangExt.UnliftedDatatypes]
+    TcRnClassKindNotConstraint{}
+      -> noHints
+    TcRnUnpromotableThing{}
+      -> noHints
 
 deriveInstanceErrReasonHints :: Class
                              -> UsingGeneralizedNewtypeDeriving
diff --git a/compiler/GHC/Tc/Errors/Types.hs b/compiler/GHC/Tc/Errors/Types.hs
index 30780d9d0edfaaf8ef52feb3caf76284c5990d5d..b86f1d1506c3f00a06afd29258df924c448ffa8d 100644
--- a/compiler/GHC/Tc/Errors/Types.hs
+++ b/compiler/GHC/Tc/Errors/Types.hs
@@ -14,6 +14,9 @@ module GHC.Tc.Errors.Types (
   , hasKinds
   , SuggestUndecidableInstances(..)
   , suggestUndecidableInstances
+  , SuggestUnliftedTypes(..)
+  , DataSort(..), ppDataSort
+  , AllowedDataResKind(..)
   , NotClosedReason(..)
   , SuggestPartialTypeSignatures(..)
   , suggestPartialTypeSignatures
@@ -52,6 +55,7 @@ module GHC.Tc.Errors.Types (
   , ValidHoleFits(..), noValidHoleFits
   , HoleFitDispConfig(..)
   , RelevantBindings(..), pprRelevantBindings
+  , PromotionErr(..), pprPECategory, peCategory
   , NotInScopeError(..), mkTcRnNotInScope
   , ImportError(..)
   , HoleError(..)
@@ -65,7 +69,7 @@ module GHC.Tc.Errors.Types (
 import GHC.Prelude
 
 import GHC.Hs
-import {-# SOURCE #-} GHC.Tc.Types (TcIdSigInfo)
+import {-# SOURCE #-} GHC.Tc.Types (TcIdSigInfo, TcTyThing)
 import {-# SOURCE #-} GHC.Tc.Errors.Hole.FitTypes (HoleFit)
 import GHC.Tc.Types.Constraint
 import GHC.Tc.Types.Evidence (EvBindsVar)
@@ -101,7 +105,7 @@ import GHC.Driver.Backend (Backend)
 import GHC.Unit.State (UnitState)
 import GHC.Unit.Module.Name (ModuleName)
 import GHC.Types.Basic
-import GHC.Utils.Misc (filterOut)
+import GHC.Utils.Misc (capitalise, filterOut)
 import qualified GHC.LanguageExtensions as LangExt
 import GHC.Data.FastString (FastString)
 
@@ -1790,6 +1794,220 @@ data TcRnMessage where
   -}
   TcRnInvalidCIdentifier :: !CLabelString -> TcRnMessage
 
+  {- TcRnExpectedValueId is an error occurring when something that is not a
+      value identifier is used where one is expected.
+
+     Example(s): none
+
+    Test cases: none
+  -}
+  TcRnExpectedValueId :: !TcTyThing -> TcRnMessage
+
+  {- TcRnNotARecordSelector is an error for when something that is not a record
+     selector is used in a record pattern.
+
+     Example(s):
+     data Rec = MkRec { field :: Int }
+     r = Mkrec 1
+     r' = r { notAField = 2 }
+
+    Test cases: rename/should_fail/rnfail054
+                typecheck/should_fail/tcfail114
+  -}
+  TcRnNotARecordSelector :: !Name -> TcRnMessage
+
+  {- TcRnRecSelectorEscapedTyVar is an error indicating that a record field selector
+     containing an existential type variable is used as a function rather than in
+     a pattern match.
+
+     Example(s):
+     data Rec = forall a. Rec { field :: a }
+     field (Rec True)
+
+    Test cases: patsyn/should_fail/records-exquant
+                typecheck/should_fail/T3176
+  -}
+  TcRnRecSelectorEscapedTyVar :: !OccName -> TcRnMessage
+
+  {- TcRnPatSynNotBidirectional is an error for when a non-bidirectional pattern
+     synonym is used as a constructor.
+
+     Example(s):
+     pattern Five :: Int
+     pattern Five <- 5
+     five = Five
+
+    Test cases: patsyn/should_fail/records-no-uni-update
+                patsyn/should_fail/records-no-uni-update2
+  -}
+  TcRnPatSynNotBidirectional :: !Name -> TcRnMessage
+
+  {- TcRnSplicePolymorphicLocalVar is the error that occurs when the expression
+     inside typed template haskell brackets is a polymorphic local variable.
+
+     Example(s):
+     x = \(y :: forall a. a -> a) -> [|| y ||]
+
+    Test cases: quotes/T10384
+  -}
+  TcRnSplicePolymorphicLocalVar :: !Id -> TcRnMessage
+
+  {- TcRnIllegalDerivingItem is an error for when something other than a type class
+     appears in a deriving statement.
+
+     Example(s):
+     data X = X deriving Int
+
+    Test cases: deriving/should_fail/T5922
+  -}
+  TcRnIllegalDerivingItem :: !(LHsSigType GhcRn) -> TcRnMessage
+
+  {- TcRnUnexpectedAnnotation indicates the erroroneous use of an annotation such
+     as strictness, laziness, or unpacking.
+
+     Example(s):
+     data T = T { t :: Maybe {-# UNPACK #-} Int }
+     data C = C { f :: !IntMap Int }
+
+    Test cases: parser/should_fail/unpack_inside_type
+                typecheck/should_fail/T7210
+  -}
+  TcRnUnexpectedAnnotation :: !(HsType GhcRn) -> !HsSrcBang -> TcRnMessage
+
+  {- TcRnIllegalRecordSyntax is an error indicating an illegal use of record syntax.
+
+     Example(s):
+     data T = T Int { field :: Int }
+
+    Test cases: rename/should_fail/T7943
+                rename/should_fail/T9077
+  -}
+  TcRnIllegalRecordSyntax :: !(HsType GhcRn) -> TcRnMessage
+
+  {- TcRnUnexpectedTypeSplice is an error for a typed template haskell splice
+     appearing unexpectedly.
+
+     Example(s): none
+
+    Test cases: none
+  -}
+  TcRnUnexpectedTypeSplice :: !(HsType GhcRn) -> TcRnMessage
+
+  {- TcRnInvalidVisibleKindArgument is an error for a kind application on a
+     target type that cannot accept it.
+
+     Example(s):
+     bad :: Int @Type
+     bad = 1
+     type Foo :: forall a {b}. a -> b -> b
+     type Foo x y = y
+     type Bar = Foo @Bool @Int True 42
+
+    Test cases: indexed-types/should_fail/T16356_Fail3
+                typecheck/should_fail/ExplicitSpecificity7
+                typecheck/should_fail/T12045b
+                typecheck/should_fail/T12045c
+                typecheck/should_fail/T15592a
+                typecheck/should_fail/T15816
+  -}
+  TcRnInvalidVisibleKindArgument
+    :: !(LHsType GhcRn) -- ^ The visible kind argument
+    -> !Type -- ^ Target of the kind application
+    -> TcRnMessage
+
+  {- TcRnTooManyBinders is an error for a type constructor that is declared with
+     more arguments then its kind specifies.
+
+     Example(s):
+     type T :: Type -> (Type -> Type) -> Type
+     data T a (b :: Type -> Type) x1 (x2 :: Type -> Type)
+
+    Test cases: saks/should_fail/saks_fail008
+  -}
+  TcRnTooManyBinders :: !Kind -> ![LHsTyVarBndr () GhcRn] -> TcRnMessage
+
+  {- TcRnDifferentNamesForTyVar is an error that indicates different names being
+     used for the same type variable.
+
+     Example(s):
+     data SameKind :: k -> k -> *
+     data Q (a :: k1) (b :: k2) c = MkQ (SameKind a b)
+
+    Test cases: polykinds/T11203
+                polykinds/T11821a
+                saks/should_fail/T20916
+                typecheck/should_fail/T17566b
+                typecheck/should_fail/T17566c
+  -}
+  TcRnDifferentNamesForTyVar :: !Name -> !Name -> TcRnMessage
+
+  {- TcRnInvalidReturnKind is an error for a data declaration that has a kind signature
+     with an invalid result kind.
+
+     Example(s):
+     data family Foo :: Constraint
+
+    Test cases: typecheck/should_fail/T14048b
+                typecheck/should_fail/UnliftedNewtypesConstraintFamily
+                typecheck/should_fail/T12729
+                typecheck/should_fail/T15883
+                typecheck/should_fail/T16829a
+                typecheck/should_fail/T16829b
+                typecheck/should_fail/UnliftedNewtypesNotEnabled
+                typecheck/should_fail/tcfail079
+  -}
+  TcRnInvalidReturnKind
+    :: !DataSort -- ^ classification of thing being returned
+    -> !AllowedDataResKind -- ^ allowed kind
+    -> !Kind -- ^ the return kind
+    -> !(Maybe SuggestUnliftedTypes) -- ^ suggested extension
+    -> TcRnMessage
+
+  {- TcRnClassKindNotConstraint is an error for a type class that has a kind that
+     is not equivalent to Constraint.
+
+     Example(s):
+     type C :: Type -> Type
+     class C a
+
+    Test cases: saks/should_fail/T16826
+  -}
+  TcRnClassKindNotConstraint :: !Kind -> TcRnMessage
+
+  {- TcRnUnpromotableThing is an error that occurs when the user attempts to
+     use the promoted version of something which is not promotable.
+
+     Example(s):
+     data T :: T -> *
+     data X a where
+       MkX :: Show a => a -> X a
+     foo :: Proxy ('MkX 'True)
+     foo = Proxy
+
+    Test cases: dependent/should_fail/PromotedClass
+                dependent/should_fail/T14845_fail1
+                dependent/should_fail/T14845_fail2
+                dependent/should_fail/T15215
+                dependent/should_fail/T13780c
+                dependent/should_fail/T15245
+                polykinds/T5716
+                polykinds/T5716a
+                polykinds/T6129
+                polykinds/T7433
+                patsyn/should_fail/T11265
+                patsyn/should_fail/T9161-1
+                patsyn/should_fail/T9161-2
+                dependent/should_fail/SelfDep
+                polykinds/PolyKinds06
+                polykinds/PolyKinds07
+                polykinds/T13625
+                polykinds/T15116
+                polykinds/T15116a
+                saks/should_fail/T16727a
+                saks/should_fail/T16727b
+  -}
+  TcRnUnpromotableThing :: !Name -> !PromotionErr -> TcRnMessage
+
 -- | Specifies which backend code generators where expected for an FFI declaration
 data ExpectedBackends
   = COrAsmOrLlvm         -- ^ C, Asm, or LLVM
@@ -1873,6 +2091,44 @@ suggestUndecidableInstances :: Bool -> SuggestUndecidableInstances
 suggestUndecidableInstances True  = YesSuggestUndecidableInstaces
 suggestUndecidableInstances False = NoSuggestUndecidableInstaces
 
+data SuggestUnliftedTypes
+  = SuggestUnliftedNewtypes
+  | SuggestUnliftedDatatypes
+
+-- | A description of whether something is a
+--
+-- * @data@ or @newtype@ ('DataDeclSort')
+--
+-- * @data instance@ or @newtype instance@ ('DataInstanceSort')
+--
+-- * @data family@ ('DataFamilySort')
+--
+-- At present, this data type is only consumed by 'checkDataKindSig'.
+data DataSort
+  = DataDeclSort     NewOrData
+  | DataInstanceSort NewOrData
+  | DataFamilySort
+
+ppDataSort :: DataSort -> SDoc
+ppDataSort data_sort = text $
+  case data_sort of
+    DataDeclSort     DataType -> "Data type"
+    DataDeclSort     NewType  -> "Newtype"
+    DataInstanceSort DataType -> "Data instance"
+    DataInstanceSort NewType  -> "Newtype instance"
+    DataFamilySort            -> "Data family"
+
+-- | Helper type used in 'checkDataKindSig'.
+--
+-- Superficially similar to 'ContextKind', but it lacks 'AnyKind'
+-- and 'AnyBoxedKind', and instead of @'TheKind' liftedTypeKind@
+-- provides 'LiftedKind', which is much simpler to match on and
+-- handle in 'isAllowedDataResKind'.
+data AllowedDataResKind
+  = AnyTYPEKind
+  | AnyBoxedKind
+  | LiftedKind
+
 -- | A data type to describe why a variable is not closed.
 -- See Note [Not-closed error messages] in GHC.Tc.Gen.Expr
 data NotClosedReason = NotLetBoundReason
@@ -2710,6 +2966,47 @@ discardMsg :: SDoc
 discardMsg = text "(Some bindings suppressed;" <+>
              text "use -fmax-relevant-binds=N or -fno-max-relevant-binds)"
 
+data PromotionErr
+  = TyConPE          -- TyCon used in a kind before we are ready
+                     --     data T :: T -> * where ...
+  | ClassPE          -- Ditto Class
+
+  | FamDataConPE     -- Data constructor for a data family
+                     -- See Note [AFamDataCon: not promoting data family constructors]
+                     -- in GHC.Tc.Utils.Env.
+  | ConstrainedDataConPE PredType
+                     -- Data constructor with a non-equality context
+                     -- See Note [Don't promote data constructors with
+                     --           non-equality contexts] in GHC.Tc.Gen.HsType
+  | PatSynPE         -- Pattern synonyms
+                     -- See Note [Don't promote pattern synonyms] in GHC.Tc.Utils.Env
+
+  | RecDataConPE     -- Data constructor in a recursive loop
+                     -- See Note [Recursion and promoting data constructors] in GHC.Tc.TyCl
+  | NoDataKindsDC    -- -XDataKinds not enabled (for a datacon)
+
+instance Outputable PromotionErr where
+  ppr ClassPE                     = text "ClassPE"
+  ppr TyConPE                     = text "TyConPE"
+  ppr PatSynPE                    = text "PatSynPE"
+  ppr FamDataConPE                = text "FamDataConPE"
+  ppr (ConstrainedDataConPE pred) = text "ConstrainedDataConPE"
+                                      <+> parens (ppr pred)
+  ppr RecDataConPE                = text "RecDataConPE"
+  ppr NoDataKindsDC               = text "NoDataKindsDC"
+
+pprPECategory :: PromotionErr -> SDoc
+pprPECategory = text . capitalise . peCategory
+
+peCategory :: PromotionErr -> String
+peCategory ClassPE                = "class"
+peCategory TyConPE                = "type constructor"
+peCategory PatSynPE               = "pattern synonym"
+peCategory FamDataConPE           = "data constructor"
+peCategory ConstrainedDataConPE{} = "data constructor"
+peCategory RecDataConPE           = "data constructor"
+peCategory NoDataKindsDC          = "data constructor"
+
 -- | Stores the information to be reported in a representation-polymorphism
 -- error message.
 data FixedRuntimeRepErrorInfo
diff --git a/compiler/GHC/Tc/Gen/Head.hs b/compiler/GHC/Tc/Gen/Head.hs
index 0212966934ec5422d804a5c10707a149e926bec2..296b223c8a66c37a4d4b26594807d8ecab3b9fc6 100644
--- a/compiler/GHC/Tc/Gen/Head.hs
+++ b/compiler/GHC/Tc/Gen/Head.hs
@@ -497,8 +497,7 @@ tcInferRecSelId (FieldOcc sel_name lbl)
                            -- nor does it need the 'lifting' treatment
                            -- hence no checkTh stuff here
 
-                    _ -> failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-                         ppr thing <+> text "used where a value identifier was expected" }
+                    _ -> failWithTc $ TcRnExpectedValueId thing }
 
 ------------------------
 
@@ -553,16 +552,7 @@ fieldNotInType p rdr
     UnknownSubordinate (text "field of type" <+> quotes (ppr p))
 
 notSelector :: Name -> TcRnMessage
-notSelector field
-  = TcRnUnknownMessage $ mkPlainError noHints $
-  hsep [quotes (ppr field), text "is not a record selector"]
-
-naughtyRecordSel :: OccName -> TcRnMessage
-naughtyRecordSel lbl
-  = TcRnUnknownMessage $ mkPlainError noHints $
-    text "Cannot use record selector" <+> quotes (ppr lbl) <+>
-    text "as a function due to escaped type variables" $$
-    text "Probable fix: use pattern-matching syntax instead"
+notSelector = TcRnNotARecordSelector
 
 
 {- *********************************************************************
@@ -755,8 +745,7 @@ tc_infer_id id_name
              (tcTyThingTyCon_maybe -> Just tc) -> fail_tycon tc -- TyCon or TcTyCon
              ATyVar name _ -> fail_tyvar name
 
-             _ -> failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-                  ppr thing <+> text "used where a value identifier was expected" }
+             _ -> failWithTc $ TcRnExpectedValueId thing }
   where
     fail_tycon tc = do
       gre <- getGlobalRdrEnv
@@ -803,7 +792,7 @@ check_local_id id
 
 check_naughty :: OccName -> TcId -> TcM ()
 check_naughty lbl id
-  | isNaughtyRecordSelector id = failWithTc (naughtyRecordSel lbl)
+  | isNaughtyRecordSelector id = failWithTc (TcRnRecSelectorEscapedTyVar lbl)
   | otherwise                  = return ()
 
 tcInferDataCon :: DataCon -> TcM (HsExpr GhcTc, TcSigmaType)
@@ -840,10 +829,8 @@ tcInferPatSyn id_name ps
        Just (expr,ty) -> return (expr,ty)
        Nothing        -> failWithTc (nonBidirectionalErr id_name)
 
-nonBidirectionalErr :: Outputable name => name -> TcRnMessage
-nonBidirectionalErr name = TcRnUnknownMessage $ mkPlainError noHints $
-  text "non-bidirectional pattern synonym"
-  <+> quotes (ppr name) <+> text "used in an expression"
+nonBidirectionalErr :: Name -> TcRnMessage
+nonBidirectionalErr = TcRnPatSynNotBidirectional
 
 {- Note [Typechecking data constructors]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1007,7 +994,7 @@ checkCrossStageLifting top_lvl id (Brack _ (TcPending ps_var lie_var q))
         -- bindings of the same splice proxy, but that doesn't
         -- matter, although it's a mite untidy.
     do  { let id_ty = idType id
-        ; checkTc (isTauTy id_ty) (polySpliceErr id)
+        ; checkTc (isTauTy id_ty) (TcRnSplicePolymorphicLocalVar id)
                -- If x is polymorphic, its occurrence sites might
                -- have different instantiations, so we can't use plain
                -- 'x' as the splice proxy name.  I don't know how to
@@ -1041,11 +1028,6 @@ checkCrossStageLifting top_lvl id (Brack _ (TcPending ps_var lie_var q))
 
 checkCrossStageLifting _ _ _ = return ()
 
-polySpliceErr :: Id -> TcRnMessage
-polySpliceErr id
-  = TcRnUnknownMessage $ mkPlainError noHints $
-  text "Can't splice the polymorphic local variable" <+> quotes (ppr id)
-
 {-
 Note [Lifting strings]
 ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/GHC/Tc/Gen/HsType.hs b/compiler/GHC/Tc/Gen/HsType.hs
index b3d6a69977b073a2d3bcbce61caa0a63e31b79a5..f2e5c92d11ced4beaead510cc220912639aeefb4 100644
--- a/compiler/GHC/Tc/Gen/HsType.hs
+++ b/compiler/GHC/Tc/Gen/HsType.hs
@@ -634,8 +634,7 @@ tcHsDeriv hs_ty
              (kind_args, _) = splitFunTys (tcTypeKind pred)
        ; case getClassPredTys_maybe pred of
            Just (cls, tys) -> return (tvs, cls, tys, map scaledThing kind_args)
-           Nothing -> failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-             (text "Illegal deriving item" <+> quotes (ppr hs_ty)) }
+           Nothing -> failWithTc $ TcRnIllegalDerivingItem hs_ty }
 
 -- | Typecheck a deriving strategy. For most deriving strategies, this is a
 -- no-op, but for the @via@ strategy, this requires typechecking the @via@ type.
@@ -1132,19 +1131,11 @@ tc_hs_type _ ty@(HsBangTy _ bang _) _
     -- While top-level bangs at this point are eliminated (eg !(Maybe Int)),
     -- other kinds of bangs are not (eg ((!Maybe) Int)). These kinds of
     -- bangs are invalid, so fail. (#7210, #14761)
-    = do { let bangError err = failWith $ TcRnUnknownMessage $ mkPlainError noHints $
-                 text "Unexpected" <+> text err <+> text "annotation:" <+> ppr ty $$
-                 text err <+> text "annotation cannot appear nested inside a type"
-         ; case bang of
-             HsSrcBang _ SrcUnpack _           -> bangError "UNPACK"
-             HsSrcBang _ SrcNoUnpack _         -> bangError "NOUNPACK"
-             HsSrcBang _ NoSrcUnpack SrcLazy   -> bangError "laziness"
-             HsSrcBang _ _ _                   -> bangError "strictness" }
+    = failWith $ TcRnUnexpectedAnnotation ty bang
 tc_hs_type _ ty@(HsRecTy {})      _
       -- Record types (which only show up temporarily in constructor
       -- signatures) should have been removed by now
-    = failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-       (text "Record syntax is illegal here:" <+> ppr ty)
+    = failWithTc $ TcRnIllegalRecordSyntax ty
 
 -- HsSpliced is an annotation produced by 'GHC.Rename.Splice.rnSpliceType'.
 -- Here we get rid of it and add the finalizers to the global environment
@@ -1158,8 +1149,7 @@ tc_hs_type mode (HsSpliceTy _ (HsSpliced _ mod_finalizers (HsSplicedTy ty)))
 
 -- This should never happen; type splices are expanded by the renamer
 tc_hs_type _ ty@(HsSpliceTy {}) _exp_kind
-  = failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-     (text "Unexpected type splice:" <+> ppr ty)
+  = failWithTc $ TcRnUnexpectedTypeSplice ty
 
 ---------- Functions and applications
 tc_hs_type mode (HsFunTy _ mult ty1 ty2) exp_kind
@@ -1707,10 +1697,7 @@ tcInferTyApps_nosat mode orig_hs_ty fun orig_hs_args
     n_initial_val_args _                    = 0
 
     ty_app_err arg ty
-      = failWith $ TcRnUnknownMessage $ mkPlainError noHints $
-          text "Cannot apply function of kind" <+> quotes (ppr ty)
-            $$ text "to visible kind argument" <+> quotes (ppr arg)
-
+      = failWith $ TcRnInvalidVisibleKindArgument arg ty
 
 mkAppTyM :: TCvSubst
          -> TcType -> TyCoBinder    -- fun, plus its top-level binder
@@ -2641,7 +2628,7 @@ matchUpSigWithDecl sig_tcbs sig_res_kind hs_bndrs thing_inside
            ; return ([], res) }
 
     go _ [] hs_bndrs
-      = failWithTc (tooManyBindersErr sig_res_kind hs_bndrs)
+      = failWithTc (TcRnTooManyBinders sig_res_kind hs_bndrs)
 
     go subst (tcb : tcbs') hs_bndrs
       | Bndr tv vis <- tcb
@@ -2700,13 +2687,6 @@ swizzleTcb swizzle_env subst (Bndr tv vis)
     -- See Note [Source locations for implicitly bound type variables]
     -- in GHC.Tc.Rename.HsType
 
-tooManyBindersErr :: Kind -> [LHsTyVarBndr () GhcRn] -> TcRnMessage
-tooManyBindersErr ki bndrs = TcRnUnknownMessage $ mkPlainError noHints $
-   hang (text "Not a function kind:")
-      4 (ppr ki) $$
-   hang (text "but extra binders found:")
-      4 (fsep (map ppr bndrs))
-
 {- See Note [kcCheckDeclHeader_sig]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Given a kind signature 'sig_kind' and a declaration header,
@@ -3022,15 +3002,7 @@ checkForDuplicateScopedTyVars scoped_prs
     report_dup :: (Name,Name) -> TcM ()
     report_dup (n1,n2)
       = setSrcSpan (getSrcSpan n2) $
-        addErrTc $ TcRnUnknownMessage $ mkPlainError noHints $
-        hang (text "Different names for the same type variable:") 2 info
-      where
-        info | nameOccName n1 /= nameOccName n2
-             = quotes (ppr n1) <+> text "and" <+> quotes (ppr n2)
-             | otherwise -- Same OccNames! See C2 in
-                         -- Note [Swizzling the tyvars before generaliseTcTyCon]
-             = vcat [ quotes (ppr n1) <+> text "bound at" <+> ppr (getSrcLoc n1)
-                    , quotes (ppr n2) <+> text "bound at" <+> ppr (getSrcLoc n2) ]
+        addErrTc $ TcRnDifferentNamesForTyVar n1 n2
 
 
 {- *********************************************************************
@@ -3753,31 +3725,6 @@ splitTyConKind skol_info in_scope avoid_occs kind
 
         ; return (go new_occs new_uniqs subst [] kind) }
 
--- | A description of whether something is a
---
--- * @data@ or @newtype@ ('DataDeclSort')
---
--- * @data instance@ or @newtype instance@ ('DataInstanceSort')
---
--- * @data family@ ('DataFamilySort')
---
--- At present, this data type is only consumed by 'checkDataKindSig'.
-data DataSort
-  = DataDeclSort     NewOrData
-  | DataInstanceSort NewOrData
-  | DataFamilySort
-
--- | Local helper type used in 'checkDataKindSig'.
---
--- Superficially similar to 'ContextKind', but it lacks 'AnyKind'
--- and 'AnyBoxedKind', and instead of @'TheKind' liftedTypeKind@
--- provides 'LiftedKind', which is much simpler to match on and
--- handle in 'isAllowedDataResKind'.
-data AllowedDataResKind
-  = AnyTYPEKind
-  | AnyBoxedKind
-  | LiftedKind
-
 isAllowedDataResKind :: AllowedDataResKind -> Kind -> Bool
 isAllowedDataResKind AnyTYPEKind  kind = tcIsRuntimeTypeKind kind
 isAllowedDataResKind AnyBoxedKind kind = tcIsBoxedTypeKind kind
@@ -3814,15 +3761,6 @@ checkDataKindSig data_sort kind
        -- Look for the result kind after
        -- peeling off any foralls and arrows
 
-    pp_dec :: SDoc
-    pp_dec = text $
-      case data_sort of
-        DataDeclSort     DataType -> "Data type"
-        DataDeclSort     NewType  -> "Newtype"
-        DataInstanceSort DataType -> "Data instance"
-        DataInstanceSort NewType  -> "Newtype instance"
-        DataFamilySort            -> "Data family"
-
     is_newtype :: Bool
     is_newtype =
       case data_sort of
@@ -3875,32 +3813,21 @@ checkDataKindSig data_sort kind
     is_kind_var | is_data_family = isJust (tcGetCastedTyVar_maybe res_kind)
                 | otherwise      = False
 
-    pp_allowed_kind dflags =
-      case allowed_kind dflags of
-        AnyTYPEKind  -> ppr tYPETyCon
-        AnyBoxedKind -> ppr boxedRepDataConTyCon
-        LiftedKind   -> ppr liftedTypeKind
-
     err_msg :: DynFlags -> TcRnMessage
-    err_msg dflags = TcRnUnknownMessage $ mkPlainError noHints $
-      sep [ sep [ pp_dec <+>
-                  text "has non-" <>
-                  pp_allowed_kind dflags
-                , (if is_data_family then text "and non-variable" else empty) <+>
-                  text "return kind" <+> quotes (ppr kind) ]
-          , ext_hint dflags ]
+    err_msg dflags =
+      TcRnInvalidReturnKind data_sort (allowed_kind dflags) kind (ext_hint dflags)
 
     ext_hint dflags
       | tcIsRuntimeTypeKind kind
       , is_newtype
       , not (xopt LangExt.UnliftedNewtypes dflags)
-      = text "Perhaps you intended to use UnliftedNewtypes"
+      = Just SuggestUnliftedNewtypes
       | tcIsBoxedTypeKind kind
       , is_datatype
       , not (xopt LangExt.UnliftedDatatypes dflags)
-      = text "Perhaps you intended to use UnliftedDatatypes"
+      = Just SuggestUnliftedDatatypes
       | otherwise
-      = empty
+      = Nothing
 
 -- | Checks that the result kind of a class is exactly `Constraint`, rejecting
 -- type synonyms and type families that reduce to `Constraint`. See #16826.
@@ -3908,9 +3835,7 @@ checkClassKindSig :: Kind -> TcM ()
 checkClassKindSig kind = checkTc (tcIsConstraintKind kind) err_msg
   where
     err_msg :: TcRnMessage
-    err_msg = TcRnUnknownMessage $ mkPlainError noHints $
-      text "Kind signature on a class must end with" <+> ppr constraintKind $$
-      text "unobscured by type families"
+    err_msg = TcRnClassKindNotConstraint kind
 
 tcbVisibilities :: TyCon -> [Type] -> [TyConBndrVis]
 -- Result is in 1-1 correspondence with orig_args
@@ -4378,22 +4303,7 @@ tc_lhs_kind_sig mode ctxt hs_kind
 
 promotionErr :: Name -> PromotionErr -> TcM a
 promotionErr name err
-  = failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
-      (hang (pprPECategory err <+> quotes (ppr name) <+> text "cannot be used here")
-                   2 (parens reason))
-  where
-    reason = case err of
-               ConstrainedDataConPE pred
-                              -> text "it has an unpromotable context"
-                                 <+> quotes (ppr pred)
-               FamDataConPE   -> text "it comes from a data family instance"
-               NoDataKindsDC  -> text "perhaps you intended to use DataKinds"
-               PatSynPE       -> text "pattern synonyms cannot be promoted"
-               RecDataConPE   -> same_rec_group_msg
-               ClassPE        -> same_rec_group_msg
-               TyConPE        -> same_rec_group_msg
-
-    same_rec_group_msg = text "it is defined and used in the same recursive group"
+  = failWithTc $ TcRnUnpromotableThing name err
 
 {-
 ************************************************************************
diff --git a/compiler/GHC/Tc/Types.hs b/compiler/GHC/Tc/Types.hs
index d837b629ec4134930f86848778f49e291b1f8555..bce78dda31ba72ae3c3dcd1511a735a55117d028 100644
--- a/compiler/GHC/Tc/Types.hs
+++ b/compiler/GHC/Tc/Types.hs
@@ -1147,25 +1147,6 @@ tcTyThingTyCon_maybe (AGlobal (ATyCon tc)) = Just tc
 tcTyThingTyCon_maybe (ATcTyCon tc_tc)      = Just tc_tc
 tcTyThingTyCon_maybe _                     = Nothing
 
-data PromotionErr
-  = TyConPE          -- TyCon used in a kind before we are ready
-                     --     data T :: T -> * where ...
-  | ClassPE          -- Ditto Class
-
-  | FamDataConPE     -- Data constructor for a data family
-                     -- See Note [AFamDataCon: not promoting data family constructors]
-                     -- in GHC.Tc.Utils.Env.
-  | ConstrainedDataConPE PredType
-                     -- Data constructor with a non-equality context
-                     -- See Note [Don't promote data constructors with
-                     --           non-equality contexts] in GHC.Tc.Gen.HsType
-  | PatSynPE         -- Pattern synonyms
-                     -- See Note [Don't promote pattern synonyms] in GHC.Tc.Utils.Env
-
-  | RecDataConPE     -- Data constructor in a recursive loop
-                     -- See Note [Recursion and promoting data constructors] in GHC.Tc.TyCl
-  | NoDataKindsDC    -- -XDataKinds not enabled (for a datacon)
-
 instance Outputable TcTyThing where     -- Debugging only
    ppr (AGlobal g)      = ppr g
    ppr elt@(ATcId {})   = text "Identifier" <>
@@ -1350,16 +1331,6 @@ instance Outputable IdBindingInfo where
   ppr (NonClosedLet fvs closed_type) =
     text "TopLevelLet" <+> ppr fvs <+> ppr closed_type
 
-instance Outputable PromotionErr where
-  ppr ClassPE                     = text "ClassPE"
-  ppr TyConPE                     = text "TyConPE"
-  ppr PatSynPE                    = text "PatSynPE"
-  ppr FamDataConPE                = text "FamDataConPE"
-  ppr (ConstrainedDataConPE pred) = text "ConstrainedDataConPE"
-                                      <+> parens (ppr pred)
-  ppr RecDataConPE                = text "RecDataConPE"
-  ppr NoDataKindsDC               = text "NoDataKindsDC"
-
 --------------
 pprTcTyThingCategory :: TcTyThing -> SDoc
 pprTcTyThingCategory = text . capitalise . tcTyThingCategory
@@ -1371,19 +1342,6 @@ tcTyThingCategory (ATcId {})         = "local identifier"
 tcTyThingCategory (ATcTyCon {})      = "local tycon"
 tcTyThingCategory (APromotionErr pe) = peCategory pe
 
---------------
-pprPECategory :: PromotionErr -> SDoc
-pprPECategory = text . capitalise . peCategory
-
-peCategory :: PromotionErr -> String
-peCategory ClassPE                = "class"
-peCategory TyConPE                = "type constructor"
-peCategory PatSynPE               = "pattern synonym"
-peCategory FamDataConPE           = "data constructor"
-peCategory ConstrainedDataConPE{} = "data constructor"
-peCategory RecDataConPE           = "data constructor"
-peCategory NoDataKindsDC          = "data constructor"
-
 {-
 ************************************************************************
 *                                                                      *
diff --git a/compiler/GHC/Tc/Types.hs-boot b/compiler/GHC/Tc/Types.hs-boot
index 9f107936a51906fe613262d1caefdefec1414b7c..42df1f4bc0164b0dfbeb013dee3de34454c26a0f 100644
--- a/compiler/GHC/Tc/Types.hs-boot
+++ b/compiler/GHC/Tc/Types.hs-boot
@@ -11,6 +11,9 @@ data SelfBootInfo
 data TcIdSigInfo
 instance Outputable TcIdSigInfo
 
+data TcTyThing
+instance Outputable TcTyThing
+
 setLclEnvTcLevel :: TcLclEnv -> TcLevel -> TcLclEnv
 getLclEnvTcLevel :: TcLclEnv -> TcLevel
 
diff --git a/compiler/GHC/Types/Hint.hs b/compiler/GHC/Types/Hint.hs
index cbdb8d532199f466f51dc1880e8c7d5a66e74683..25b66c0283c85db5465b34bfe0a5258256134e20 100644
--- a/compiler/GHC/Types/Hint.hs
+++ b/compiler/GHC/Types/Hint.hs
@@ -393,11 +393,16 @@ data GhcHint
         Test cases: ccfail004
     -}
   | SuggestImportingDataCon
-
   {- Found a pragma in the body of a module, suggest
      placing it in the header
   -}
   | SuggestPlacePragmaInHeader
+    {-| Suggest using pattern matching syntax for a non-bidirectional pattern synonym
+
+        Test cases: patsyn/should_fail/record-exquant
+                    typecheck/should_fail/T3176
+    -}
+  | SuggestPatternMatchingSyntax
 
 -- | An 'InstantiationSuggestion' for a '.hsig' file. This is generated
 -- by GHC in case of a 'DriverUnexpectedSignature' and suggests a way
diff --git a/compiler/GHC/Types/Hint/Ppr.hs b/compiler/GHC/Types/Hint/Ppr.hs
index fbaa2a8842b069163afba41b0865553cf9c9795e..08c5efdb36cf8f2b0b1ca2bf30b7de497dca2c89 100644
--- a/compiler/GHC/Types/Hint/Ppr.hs
+++ b/compiler/GHC/Types/Hint/Ppr.hs
@@ -197,6 +197,8 @@ instance Outputable GhcHint where
     SuggestPlacePragmaInHeader
       -> text "Perhaps you meant to place it in the module header?"
       $$ text "The module header is the section at the top of the file, before the" <+> quotes (text "module") <+> text "keyword"
+    SuggestPatternMatchingSyntax
+      -> text "Use pattern-matching syntax instead"
 
 perhapsAsPat :: SDoc
 perhapsAsPat = text "Perhaps you meant an as-pattern, which must not be surrounded by whitespace"
diff --git a/testsuite/tests/linters/notes.stdout b/testsuite/tests/linters/notes.stdout
index 16fd6a02ace2d79f2530c61ef185d84d32076bd7..2ce1e21ae1fe0fb4d28c6676d553f1fc764cd77e 100644
--- a/testsuite/tests/linters/notes.stdout
+++ b/testsuite/tests/linters/notes.stdout
@@ -58,6 +58,7 @@ ref    compiler/GHC/StgToCmm/Expr.hs:848:3:     Note [alg-alt heap check]
 ref    compiler/GHC/Tc/Errors.hs:180:13:     Note [Fail fast on kind errors]
 ref    compiler/GHC/Tc/Errors.hs:2016:0:     Note [Highlighting ambiguous type variables]
 ref    compiler/GHC/Tc/Errors/Ppr.hs:1760:11:     Note [Highlighting ambiguous type variables]
+ref    compiler/GHC/Tc/Errors/Types.hs:2986:28:     Note [Don't promote data constructors with non-equality contexts]
 ref    compiler/GHC/Tc/Gen/Arrow.hs:435:29:     Note [RecStmt]
 ref    compiler/GHC/Tc/Gen/Bind.hs:1397:19:     Note [Existentials in pattern bindings]
 ref    compiler/GHC/Tc/Gen/Export.hs:187:15:     Note [Modules without a module header]
@@ -94,7 +95,6 @@ ref    compiler/GHC/Tc/TyCl.hs:4366:16:     Note [rejigCon and c.f. Note [Check
 ref    compiler/GHC/Tc/TyCl/Instance.hs:947:26:     Note [Generalising in tcFamTyPatsGuts]
 ref    compiler/GHC/Tc/Types.hs:647:17:     Note [Generating fresh names for FFI wrappers]
 ref    compiler/GHC/Tc/Types.hs:696:33:     Note [Extra dependencies from .hs-boot files]
-ref    compiler/GHC/Tc/Types.hs:1154:28:     Note [Don't promote data constructors with non-equality contexts]
 ref    compiler/GHC/Tc/Types.hs:1230:36:     Note [Bindings with closed types]
 ref    compiler/GHC/Tc/Types.hs:1466:47:     Note [Care with plugin imports]
 ref    compiler/GHC/Tc/Types/Constraint.hs:238:34:     Note [NonCanonical Semantics]
diff --git a/testsuite/tests/patsyn/should_fail/records-exquant.stderr b/testsuite/tests/patsyn/should_fail/records-exquant.stderr
index e742ada348eb9834ddbeb8a34522521d351710f5..b5c3fddcc34ea2d042041731196de19f0d5bf27b 100644
--- a/testsuite/tests/patsyn/should_fail/records-exquant.stderr
+++ b/testsuite/tests/patsyn/should_fail/records-exquant.stderr
@@ -1,11 +1,11 @@
 
 records-exquant.hs:8:7: error:
-    Cannot use record selector ‘a’ as a function due to escaped type variables
-    Probable fix: use pattern-matching syntax instead
-    In the expression: a (Showable True)
-    In an equation for ‘qux’: qux = a (Showable True)
+    • Cannot use record selector ‘a’ as a function due to escaped type variables
+    • In the expression: a (Showable True)
+      In an equation for ‘qux’: qux = a (Showable True)
+    Suggested fix: Use pattern-matching syntax instead
 
 records-exquant.hs:10:7: error:
-    Record update for insufficiently polymorphic field: a :: a
-    In the expression: (Showable ()) {a = True}
-    In an equation for ‘foo’: foo = (Showable ()) {a = True}
+    • Record update for insufficiently polymorphic field: a :: a
+    • In the expression: (Showable ()) {a = True}
+      In an equation for ‘foo’: foo = (Showable ()) {a = True}
diff --git a/testsuite/tests/typecheck/should_fail/T12729.stderr b/testsuite/tests/typecheck/should_fail/T12729.stderr
index 6bf544fe47fd7e2a0e41471adc4db62fccf819e9..9fdcd6f940a24517bc7a982e76703896cf1f8d7b 100644
--- a/testsuite/tests/typecheck/should_fail/T12729.stderr
+++ b/testsuite/tests/typecheck/should_fail/T12729.stderr
@@ -1,5 +1,5 @@
 
 T12729.hs:7:1: error:
     • Newtype has non-* return kind ‘TYPE 'IntRep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype declaration for ‘A’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes
diff --git a/testsuite/tests/typecheck/should_fail/T15883.stderr b/testsuite/tests/typecheck/should_fail/T15883.stderr
index d65ffa5ebc284d9260f869d1c2de0637fff631d2..c66d5109328b405561cf6a5e934c58c21ca949e1 100644
--- a/testsuite/tests/typecheck/should_fail/T15883.stderr
+++ b/testsuite/tests/typecheck/should_fail/T15883.stderr
@@ -1,5 +1,5 @@
 
 T15883.hs:9:1: error:
     • Newtype has non-* return kind ‘TYPE rep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype declaration for ‘Foo’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes
diff --git a/testsuite/tests/typecheck/should_fail/T16829a.stderr b/testsuite/tests/typecheck/should_fail/T16829a.stderr
index bbad3415d680bf572737d810382e1eaf360d7e02..f53d6ccfd6cbec2de995d0987c14177cc585425c 100644
--- a/testsuite/tests/typecheck/should_fail/T16829a.stderr
+++ b/testsuite/tests/typecheck/should_fail/T16829a.stderr
@@ -1,5 +1,5 @@
 
 T16829a.hs:9:1: error:
     • Newtype has non-* return kind ‘TYPE 'IntRep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype declaration for ‘T’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes
diff --git a/testsuite/tests/typecheck/should_fail/T16829b.stderr b/testsuite/tests/typecheck/should_fail/T16829b.stderr
index 633d8988a70612d8fa9a63f20baec5fc4abc3176..9d4c5057ca5567e9bc888d81443b1e798955c009 100644
--- a/testsuite/tests/typecheck/should_fail/T16829b.stderr
+++ b/testsuite/tests/typecheck/should_fail/T16829b.stderr
@@ -1,5 +1,5 @@
 
 T16829b.hs:10:1: error:
     • Newtype instance has non-* return kind ‘TYPE 'IntRep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype instance declaration for ‘T’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes
diff --git a/testsuite/tests/typecheck/should_fail/T3176.stderr b/testsuite/tests/typecheck/should_fail/T3176.stderr
index 1f089da6fe8e48b68d37d7c8cc500ffe0e9e84eb..d2867df4a1663164894341899135049e6109968b 100644
--- a/testsuite/tests/typecheck/should_fail/T3176.stderr
+++ b/testsuite/tests/typecheck/should_fail/T3176.stderr
@@ -1,7 +1,7 @@
 
 T3176.hs:9:27: error:
     • Cannot use record selector ‘unES’ as a function due to escaped type variables
-      Probable fix: use pattern-matching syntax instead
     • In the first argument of ‘($)’, namely ‘unES’
       In the second argument of ‘($)’, namely ‘unES $ f t’
       In the expression: show $ unES $ f t
+    Suggested fix: Use pattern-matching syntax instead
diff --git a/testsuite/tests/typecheck/should_fail/UnliftedNewtypesNotEnabled.stderr b/testsuite/tests/typecheck/should_fail/UnliftedNewtypesNotEnabled.stderr
index d45f3ca0163e79591d65ae0b8e9856831d5a1eb3..59c5c523a2f5cb100aa67afd8608b15d11c7e2f1 100644
--- a/testsuite/tests/typecheck/should_fail/UnliftedNewtypesNotEnabled.stderr
+++ b/testsuite/tests/typecheck/should_fail/UnliftedNewtypesNotEnabled.stderr
@@ -1,5 +1,5 @@
 
 UnliftedNewtypesNotEnabled.hs:9:1: error:
     • Newtype has non-* return kind ‘TYPE 'GHC.Types.IntRep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype declaration for ‘Baz’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes
diff --git a/testsuite/tests/typecheck/should_fail/tcfail079.stderr b/testsuite/tests/typecheck/should_fail/tcfail079.stderr
index dce069a456e78cda9d9e558a84f9b5809a642aae..8f28c7d41c9c4c9b8cea349300b4b9af5ae161ca 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail079.stderr
+++ b/testsuite/tests/typecheck/should_fail/tcfail079.stderr
@@ -1,5 +1,5 @@
 
 tcfail079.hs:9:1: error:
     • Newtype has non-* return kind ‘TYPE 'GHC.Types.IntRep’
-      Perhaps you intended to use UnliftedNewtypes
     • In the newtype declaration for ‘Unboxed’
+    Suggested fix: Perhaps you intended to use UnliftedNewtypes