From df706de378e3415a3972ddd14863f54fc7162dc7 Mon Sep 17 00:00:00 2001
From: sheaf <sam.derbyshire@gmail.com>
Date: Wed, 14 Jun 2023 18:57:28 +0200
Subject: [PATCH] Re-instate -Wincomplete-record-updates

Commit e74fc066 refactored the handling of record updates to use
the HsExpanded mechanism. This meant that the pattern matching inherent
to a record update was considered to be "generated code", and thus we
stopped emitting "incomplete record update" warnings entirely.

This commit changes the "data Origin = Source | Generated" datatype,
adding a field to the Generated constructor to indicate whether we
still want to perform pattern-match checking. We also have to do a bit
of plumbing with HsCase, to record that the HsCase arose from an
HsExpansion of a RecUpd, so that the error message continues to mention
record updates as opposed to a generic "incomplete pattern matches in case"
error.

Finally, this patch also changes the way we handle inaccessible code
warnings. Commit e74fc066 was also a regression in this regard, as we
were emitting "inaccessible code" warnings for case statements spuriously
generated when desugaring a record update (remember: the desugaring mechanism
happens before typechecking; it thus can't take into account e.g. GADT information
in order to decide which constructors to include in the RHS of the desugaring
of the record update).
We fix this by changing the mechanism through which we disable inaccessible
code warnings: we now check whether we are in generated code in
GHC.Tc.Utils.TcMType.newImplication in order to determine whether to
emit inaccessible code warnings.

Fixes #23520
Updates haddock submodule, to avoid incomplete record update warnings
---
 compiler/GHC/Hs/Expr.hs                       | 13 ++---
 compiler/GHC/Hs/Utils.hs                      | 11 ++--
 compiler/GHC/HsToCore/Arrows.hs               |  6 +-
 compiler/GHC/HsToCore/Errors/Ppr.hs           |  4 +-
 compiler/GHC/HsToCore/Errors/Types.hs         |  8 +--
 compiler/GHC/HsToCore/Expr.hs                 |  7 ++-
 compiler/GHC/HsToCore/GuardedRHSs.hs          |  6 +-
 compiler/GHC/HsToCore/Match.hs                | 22 +++----
 compiler/GHC/HsToCore/Match.hs-boot           |  8 +--
 compiler/GHC/HsToCore/Match/Constructor.hs    |  4 +-
 compiler/GHC/HsToCore/Monad.hs                |  2 +-
 compiler/GHC/HsToCore/Pmc.hs                  |  2 +-
 compiler/GHC/HsToCore/Pmc/Utils.hs            | 27 +++++----
 compiler/GHC/HsToCore/Utils.hs                |  2 +-
 compiler/GHC/Iface/Ext/Ast.hs                 |  2 +-
 compiler/GHC/Rename/Expr.hs                   |  2 +-
 compiler/GHC/Rename/Utils.hs                  |  4 +-
 compiler/GHC/Tc/Deriv/Generate.hs             |  6 +-
 compiler/GHC/Tc/Gen/Expr.hs                   |  5 +-
 compiler/GHC/Tc/Gen/Splice.hs                 |  2 +-
 compiler/GHC/Tc/TyCl/Instance.hs              | 12 ++--
 compiler/GHC/Tc/TyCl/PatSyn.hs                | 11 ++--
 compiler/GHC/Tc/TyCl/Utils.hs                 |  2 +-
 compiler/GHC/Tc/Types/Constraint.hs           |  3 +-
 compiler/GHC/Tc/Utils/Monad.hs                | 20 +++++--
 compiler/GHC/Tc/Utils/TcMType.hs              |  5 +-
 compiler/GHC/Types/Basic.hs                   | 57 +++++++++++++++++--
 testsuite/tests/ghc-api/T18522-dbg-ppr.hs     |  2 +-
 .../pmcheck/should_compile/T12957a.stderr     | 18 ++----
 .../tests/pmcheck/should_compile/T17783.hs    |  8 ++-
 .../tests/pmcheck/should_compile/T21360.hs    |  2 -
 .../tests/pmcheck/should_compile/T23520.hs    |  5 ++
 .../pmcheck/should_compile/T23520.stderr      |  4 ++
 testsuite/tests/pmcheck/should_compile/all.T  |  9 +--
 .../tests/typecheck/should_fail/T3323.stderr  |  6 +-
 .../typecheck/should_run/Typeable1.stderr     |  6 ++
 utils/haddock                                 |  2 +-
 37 files changed, 192 insertions(+), 123 deletions(-)
 create mode 100644 testsuite/tests/pmcheck/should_compile/T23520.hs
 create mode 100644 testsuite/tests/pmcheck/should_compile/T23520.stderr

diff --git a/compiler/GHC/Hs/Expr.hs b/compiler/GHC/Hs/Expr.hs
index da7b2b23983f..3fcb4ef1a15e 100644
--- a/compiler/GHC/Hs/Expr.hs
+++ b/compiler/GHC/Hs/Expr.hs
@@ -286,8 +286,8 @@ type instance XExplicitSum   GhcRn = NoExtField
 type instance XExplicitSum   GhcTc = [Type]
 
 type instance XCase          GhcPs = EpAnn EpAnnHsCase
-type instance XCase          GhcRn = NoExtField
-type instance XCase          GhcTc = NoExtField
+type instance XCase          GhcRn = HsMatchContext GhcTc
+type instance XCase          GhcTc = HsMatchContext GhcTc
 
 type instance XIf            GhcPs = EpAnn AnnsIf
 type instance XIf            GhcRn = NoExtField
@@ -1973,7 +1973,7 @@ matchContextErrString LambdaExpr                    = text "lambda"
 matchContextErrString (ArrowMatchCtxt c)            = matchArrowContextErrString c
 matchContextErrString ThPatSplice                   = panic "matchContextErrString"  -- Not used at runtime
 matchContextErrString ThPatQuote                    = panic "matchContextErrString"  -- Not used at runtime
-matchContextErrString PatSyn                        = panic "matchContextErrString"  -- Not used at runtime
+matchContextErrString PatSyn                        = text "pattern synonym"
 matchContextErrString (StmtCtxt (ParStmtCtxt c))    = matchContextErrString (StmtCtxt c)
 matchContextErrString (StmtCtxt (TransStmtCtxt c))  = matchContextErrString (StmtCtxt c)
 matchContextErrString (StmtCtxt (PatGuard _))       = text "pattern guard"
@@ -2030,11 +2030,10 @@ matchSeparator ArrowMatchCtxt{} = text "->"
 matchSeparator PatBindRhs       = text "="
 matchSeparator PatBindGuards    = text "="
 matchSeparator StmtCtxt{}       = text "<-"
-matchSeparator RecUpd           = text "=" -- This can be printed by the pattern
-                                       -- match checker trace
+matchSeparator RecUpd           = text "="  -- This can be printed by the pattern
+matchSeparator PatSyn           = text "<-" -- match checker trace
 matchSeparator ThPatSplice  = panic "unused"
 matchSeparator ThPatQuote   = panic "unused"
-matchSeparator PatSyn       = panic "unused"
 
 pprMatchContext :: (Outputable (IdP (NoGhcTc p)), UnXRec (NoGhcTc p))
                 => HsMatchContext p -> SDoc
@@ -2055,7 +2054,7 @@ pprMatchContextNoun CaseAlt                 = text "case alternative"
 pprMatchContextNoun (LamCaseAlt lc_variant) = lamCaseKeyword lc_variant
                                               <+> text "alternative"
 pprMatchContextNoun IfAlt                   = text "multi-way if alternative"
-pprMatchContextNoun RecUpd                  = text "record-update construct"
+pprMatchContextNoun RecUpd                  = text "record update"
 pprMatchContextNoun ThPatSplice             = text "Template Haskell pattern splice"
 pprMatchContextNoun ThPatQuote              = text "Template Haskell pattern quotation"
 pprMatchContextNoun PatBindRhs              = text "pattern binding"
diff --git a/compiler/GHC/Hs/Utils.hs b/compiler/GHC/Hs/Utils.hs
index 809278d47431..afa782103176 100644
--- a/compiler/GHC/Hs/Utils.hs
+++ b/compiler/GHC/Hs/Utils.hs
@@ -271,7 +271,7 @@ mkHsLam :: (IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ Origin)
         -> LHsExpr (GhcPass p)
 mkHsLam pats body = mkHsPar (L (getLoc body) (HsLam noExtField matches))
   where
-    matches = mkMatchGroup Generated
+    matches = mkMatchGroup (Generated SkipPmc)
                            (noLocA [mkSimpleMatch LambdaExpr pats' body])
     pats' = map (parenthesizePat appPrec) pats
 
@@ -599,7 +599,8 @@ nlHsCase :: LHsExpr GhcPs -> [LMatch GhcPs (LHsExpr GhcPs)]
 nlList   :: [LHsExpr GhcPs] -> LHsExpr GhcPs
 
 -- AZ:Is this used?
-nlHsLam match = noLocA (HsLam noExtField (mkMatchGroup Generated (noLocA [match])))
+nlHsLam match = noLocA $ HsLam noExtField
+              $ mkMatchGroup (Generated SkipPmc) (noLocA [match])
 nlHsPar e     = noLocA (gHsPar e)
 
 -- nlHsIf should generate if-expressions which are NOT subject to
@@ -608,7 +609,7 @@ nlHsIf :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
 nlHsIf cond true false = noLocA (HsIf noAnn cond true false)
 
 nlHsCase expr matches
-  = noLocA (HsCase noAnn expr (mkMatchGroup Generated (noLocA matches)))
+  = noLocA (HsCase noAnn expr (mkMatchGroup (Generated SkipPmc) (noLocA matches)))
 nlList exprs          = noLocA (ExplicitList noAnn exprs)
 
 nlHsAppTy :: LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p)
@@ -865,9 +866,9 @@ spanHsLocaLBinds (HsIPBinds _ (IPBinds _ bs))
 -- | Convenience function using 'mkFunBind'.
 -- This is for generated bindings only, do not use for user-written code.
 mkSimpleGeneratedFunBind :: SrcSpan -> RdrName -> [LPat GhcPs]
-                -> LHsExpr GhcPs -> LHsBind GhcPs
+                         -> LHsExpr GhcPs -> LHsBind GhcPs
 mkSimpleGeneratedFunBind loc fun pats expr
-  = L (noAnnSrcSpan loc) $ mkFunBind Generated (L (noAnnSrcSpan loc) fun)
+  = L (noAnnSrcSpan loc) $ mkFunBind (Generated SkipPmc) (L (noAnnSrcSpan loc) fun)
               [mkMatch (mkPrefixFunRhs (L (noAnnSrcSpan loc) fun)) pats expr
                        emptyLocalBinds]
 
diff --git a/compiler/GHC/HsToCore/Arrows.hs b/compiler/GHC/HsToCore/Arrows.hs
index cc757a94e3c3..734ad2589e91 100644
--- a/compiler/GHC/HsToCore/Arrows.hs
+++ b/compiler/GHC/HsToCore/Arrows.hs
@@ -510,7 +510,7 @@ dsCmd ids local_vars stack_ty res_ty (HsCmdCase _ exp match) env_ids = do
     let MG{ mg_ext = MatchGroupTc _ sum_ty _ } = match'
         in_ty = envStackType env_ids stack_ty
 
-    core_body <- dsExpr (HsCase noExtField exp match')
+    core_body <- dsExpr (HsCase (ArrowMatchCtxt ArrowCaseAlt) exp match')
 
     core_matches <- matchEnvStack env_ids stack_id core_body
     return (do_premap ids in_ty sum_ty res_ty core_matches core_choices,
@@ -811,7 +811,7 @@ dsCases ids local_vars stack_id stack_ty res_ty
     Nothing -> ([], void_ty,) . do_arr ids void_ty res_ty <$>
       dsExpr (HsLamCase EpAnnNotUsed LamCase
         (MG { mg_alts = noLocA []
-            , mg_ext = MatchGroupTc [Scaled ManyTy void_ty] res_ty Generated
+            , mg_ext = MatchGroupTc [Scaled ManyTy void_ty] res_ty (Generated SkipPmc)
             }))
 
       -- Replace the commands in the case with these tagged tuples,
@@ -1191,7 +1191,7 @@ dsCmdStmts _ _ _ [] _ = panic "dsCmdStmts []"
 -- Match a list of expressions against a list of patterns, left-to-right.
 
 matchSimplys :: [CoreExpr]              -- Scrutinees
-             -> HsMatchContext GhcRn    -- Match kind
+             -> HsMatchContext GhcTc    -- Match kind
              -> [LPat GhcTc]            -- Patterns they should match
              -> CoreExpr                -- Return this if they all match
              -> CoreExpr                -- Return this if they don't
diff --git a/compiler/GHC/HsToCore/Errors/Ppr.hs b/compiler/GHC/HsToCore/Errors/Ppr.hs
index 4fdc6c120fd7..cc7222f447c5 100644
--- a/compiler/GHC/HsToCore/Errors/Ppr.hs
+++ b/compiler/GHC/HsToCore/Errors/Ppr.hs
@@ -298,11 +298,11 @@ badMonadBind elt_ty
        2 (quotes (ppr elt_ty))
 
 -- Print a single clause (for redundant/with-inaccessible-rhs)
-pprEqn :: HsMatchContext GhcRn -> SDoc -> String -> SDoc
+pprEqn :: HsMatchContext GhcTc -> SDoc -> String -> SDoc
 pprEqn ctx q txt = pprContext True ctx (text txt) $ \f ->
   f (q <+> matchSeparator ctx <+> text "...")
 
-pprContext :: Bool -> HsMatchContext GhcRn -> SDoc -> ((SDoc -> SDoc) -> SDoc) -> SDoc
+pprContext :: Bool -> HsMatchContext GhcTc -> SDoc -> ((SDoc -> SDoc) -> SDoc) -> SDoc
 pprContext singular kind msg rest_of_msg_fun
   = vcat [text txt <+> msg,
           sep [ text "In" <+> ppr_match <> char ':'
diff --git a/compiler/GHC/HsToCore/Errors/Types.hs b/compiler/GHC/HsToCore/Errors/Types.hs
index 8f118abb1376..608bfa285447 100644
--- a/compiler/GHC/HsToCore/Errors/Types.hs
+++ b/compiler/GHC/HsToCore/Errors/Types.hs
@@ -85,18 +85,18 @@ data DsMessage
 
   -- FIXME(adn) Use a proper type instead of 'SDoc', but unfortunately
   -- 'SrcInfo' gives us an 'SDoc' to begin with.
-  | DsRedundantBangPatterns !(HsMatchContext GhcRn) !SDoc
+  | DsRedundantBangPatterns !(HsMatchContext GhcTc) !SDoc
 
   -- FIXME(adn) Use a proper type instead of 'SDoc', but unfortunately
   -- 'SrcInfo' gives us an 'SDoc' to begin with.
-  | DsOverlappingPatterns !(HsMatchContext GhcRn) !SDoc
+  | DsOverlappingPatterns !(HsMatchContext GhcTc) !SDoc
 
   -- FIXME(adn) Use a proper type instead of 'SDoc'
-  | DsInaccessibleRhs !(HsMatchContext GhcRn) !SDoc
+  | DsInaccessibleRhs !(HsMatchContext GhcTc) !SDoc
 
   | DsMaxPmCheckModelsReached !MaxPmCheckModels
 
-  | DsNonExhaustivePatterns !(HsMatchContext GhcRn)
+  | DsNonExhaustivePatterns !(HsMatchContext GhcTc)
                             !ExhaustivityCheckType
                             !MaxUncoveredPatterns
                             [Id]
diff --git a/compiler/GHC/HsToCore/Expr.hs b/compiler/GHC/HsToCore/Expr.hs
index fde37370acc2..be9347e0e2c8 100644
--- a/compiler/GHC/HsToCore/Expr.hs
+++ b/compiler/GHC/HsToCore/Expr.hs
@@ -373,9 +373,9 @@ dsExpr (ExplicitSum types alt arity expr)
 dsExpr (HsPragE _ prag expr) =
   ds_prag_expr prag expr
 
-dsExpr (HsCase _ discrim matches)
+dsExpr (HsCase ctxt discrim matches)
   = do { core_discrim <- dsLExpr discrim
-       ; ([discrim_var], matching_code) <- matchWrapper CaseAlt (Just [discrim]) matches
+       ; ([discrim_var], matching_code) <- matchWrapper ctxt (Just [discrim]) matches
        ; return (bindNonRec discrim_var core_discrim matching_code) }
 
 -- Pepe: The binds are in scope in the body but NOT in the binding group
@@ -755,11 +755,12 @@ dsDo ctx stmts
         later_pats   = rec_tup_pats
         rets         = map noLocA rec_rets
         mfix_app     = nlHsSyntaxApps mfix_op [mfix_arg]
+        match_group  = MatchGroupTc [unrestricted tup_ty] body_ty (Generated SkipPmc)
         mfix_arg     = noLocA $ HsLam noExtField
                            (MG { mg_alts = noLocA [mkSimpleMatch
                                                     LambdaExpr
                                                     [mfix_pat] body]
-                               , mg_ext = MatchGroupTc [unrestricted tup_ty] body_ty Generated
+                               , mg_ext = match_group
                                })
         mfix_pat     = noLocA $ LazyPat noExtField $ mkBigLHsPatTupId rec_tup_pats
         body         = noLocA $ HsDo body_ty
diff --git a/compiler/GHC/HsToCore/GuardedRHSs.hs b/compiler/GHC/HsToCore/GuardedRHSs.hs
index 6ae671668528..8a24b00a590d 100644
--- a/compiler/GHC/HsToCore/GuardedRHSs.hs
+++ b/compiler/GHC/HsToCore/GuardedRHSs.hs
@@ -55,7 +55,7 @@ dsGuarded grhss rhs_ty rhss_nablas = do
 
 -- In contrast, @dsGRHSs@ produces a @MatchResult CoreExpr@.
 
-dsGRHSs :: HsMatchContext GhcRn
+dsGRHSs :: HsMatchContext GhcTc
         -> GRHSs GhcTc (LHsExpr GhcTc) -- ^ Guarded RHSs
         -> Type                        -- ^ Type of RHS
         -> NonEmpty Nablas             -- ^ Refined pattern match checking
@@ -76,7 +76,7 @@ dsGRHSs hs_ctx (GRHSs _ grhss binds) rhs_ty rhss_nablas
                              -- NB: nested dsLet inside matchResult
        ; return match_result2 }
 
-dsGRHS :: HsMatchContext GhcRn -> Type -> Nablas -> LGRHS GhcTc (LHsExpr GhcTc)
+dsGRHS :: HsMatchContext GhcTc -> Type -> Nablas -> LGRHS GhcTc (LHsExpr GhcTc)
        -> DsM (MatchResult CoreExpr)
 dsGRHS hs_ctx rhs_ty rhs_nablas (L _ (GRHS _ guards rhs))
   = matchGuards (map unLoc guards) (PatGuard hs_ctx) rhs_nablas rhs rhs_ty
@@ -90,7 +90,7 @@ dsGRHS hs_ctx rhs_ty rhs_nablas (L _ (GRHS _ guards rhs))
 -}
 
 matchGuards :: [GuardStmt GhcTc]     -- Guard
-            -> HsStmtContext GhcRn   -- Context
+            -> HsStmtContext GhcTc   -- Context
             -> Nablas                -- The RHS's covered set for PmCheck
             -> LHsExpr GhcTc         -- RHS
             -> Type                  -- Type of RHS of guard
diff --git a/compiler/GHC/HsToCore/Match.hs b/compiler/GHC/HsToCore/Match.hs
index d6986de6fa40..6be944d1242e 100644
--- a/compiler/GHC/HsToCore/Match.hs
+++ b/compiler/GHC/HsToCore/Match.hs
@@ -28,7 +28,7 @@ import Language.Haskell.Syntax.Basic (Boxity(..))
 
 import {-#SOURCE#-} GHC.HsToCore.Expr (dsExpr)
 
-import GHC.Types.Basic ( Origin(..), isGenerated )
+import GHC.Types.Basic ( Origin(..), isGenerated, requiresPMC )
 import GHC.Types.SourceText
 import GHC.Driver.DynFlags
 import GHC.Hs
@@ -736,7 +736,7 @@ Call @match@ with all of this information!
 --                         p2 q2 -> ...
 
 matchWrapper
-  :: HsMatchContext GhcRn              -- ^ For shadowing warning messages
+  :: HsMatchContext GhcTc              -- ^ For shadowing warning messages
   -> Maybe [LHsExpr GhcTc]             -- ^ Scrutinee(s)
                                        -- see Note [matchWrapper scrutinees]
   -> MatchGroup GhcTc (LHsExpr GhcTc)  -- ^ Matches being desugared
@@ -798,7 +798,7 @@ matchWrapper ctxt scrs (MG { mg_alts = L _ matches
 
         ; eqns_info   <- zipWithM mk_eqn_info matches matches_nablas
 
-        ; result_expr <- discard_warnings_if_generated origin $
+        ; result_expr <- discard_warnings_if_skip_pmc origin $
                          matchEquations ctxt new_vars eqns_info rhs_ty
 
         ; return (new_vars, result_expr) }
@@ -818,10 +818,10 @@ matchWrapper ctxt scrs (MG { mg_alts = L _ matches
                             , eqn_orig = FromSource
                             , eqn_rhs  = match_result } }
 
-    discard_warnings_if_generated orig =
-      if isGenerated orig
-      then discardWarningsDs
-      else id
+    discard_warnings_if_skip_pmc orig =
+      if requiresPMC orig
+      then id
+      else discardWarningsDs
 
     initNablasMatches :: Nablas -> [LMatch GhcTc b] -> [(Nablas, NonEmpty Nablas)]
     initNablasMatches ldi_nablas ms
@@ -880,7 +880,7 @@ the expression (in this case, it will end up recursively calling 'matchWrapper'
 on the user-written case statement).
 -}
 
-matchEquations  :: HsMatchContext GhcRn
+matchEquations  :: HsMatchContext GhcTc
                 -> [MatchId] -> [EquationInfo] -> Type
                 -> DsM CoreExpr
 matchEquations ctxt vars eqns_info rhs_ty
@@ -894,7 +894,7 @@ matchEquations ctxt vars eqns_info rhs_ty
 -- situation where we want to match a single expression against a single
 -- pattern. It returns an expression.
 matchSimply :: CoreExpr                 -- ^ Scrutinee
-            -> HsMatchContext GhcRn     -- ^ Match kind
+            -> HsMatchContext GhcTc     -- ^ Match kind
             -> LPat GhcTc               -- ^ Pattern it should match
             -> CoreExpr                 -- ^ Return this if it matches
             -> CoreExpr                 -- ^ Return this if it doesn't
@@ -916,7 +916,7 @@ matchSimply scrut hs_ctx pat result_expr fail_expr = do
     match_result' <- matchSinglePat scrut hs_ctx pat rhs_ty match_result
     extractMatchResult match_result' fail_expr
 
-matchSinglePat :: CoreExpr -> HsMatchContext GhcRn -> LPat GhcTc
+matchSinglePat :: CoreExpr -> HsMatchContext GhcTc -> LPat GhcTc
                -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
 -- matchSinglePat ensures that the scrutinee is a variable
 -- and then calls matchSinglePatVar
@@ -942,7 +942,7 @@ matchSinglePat scrut hs_ctx pat ty match_result
 
 matchSinglePatVar :: Id   -- See Note [Match Ids]
                   -> Maybe CoreExpr -- ^ The scrutinee the match id is bound to
-                  -> HsMatchContext GhcRn -> LPat GhcTc
+                  -> HsMatchContext GhcTc -> LPat GhcTc
                   -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
 matchSinglePatVar var mb_scrut ctx pat ty match_result
   = assertPpr (isInternalName (idName var)) (ppr var) $
diff --git a/compiler/GHC/HsToCore/Match.hs-boot b/compiler/GHC/HsToCore/Match.hs-boot
index 3e969e922dd9..5a55463d4c6f 100644
--- a/compiler/GHC/HsToCore/Match.hs-boot
+++ b/compiler/GHC/HsToCore/Match.hs-boot
@@ -6,7 +6,7 @@ import GHC.Tc.Utils.TcType  ( Type )
 import GHC.HsToCore.Monad ( DsM, EquationInfo, MatchResult )
 import GHC.Core ( CoreExpr )
 import GHC.Hs   ( LPat, HsMatchContext, MatchGroup, LHsExpr )
-import GHC.Hs.Extension ( GhcTc, GhcRn )
+import GHC.Hs.Extension ( GhcTc )
 
 match   :: [Id]
         -> Type
@@ -14,14 +14,14 @@ match   :: [Id]
         -> DsM (MatchResult CoreExpr)
 
 matchWrapper
-        :: HsMatchContext GhcRn
+        :: HsMatchContext GhcTc
         -> Maybe [LHsExpr GhcTc]
         -> MatchGroup GhcTc (LHsExpr GhcTc)
         -> DsM ([Id], CoreExpr)
 
 matchSimply
         :: CoreExpr
-        -> HsMatchContext GhcRn
+        -> HsMatchContext GhcTc
         -> LPat GhcTc
         -> CoreExpr
         -> CoreExpr
@@ -30,7 +30,7 @@ matchSimply
 matchSinglePatVar
         :: Id
         -> Maybe CoreExpr
-        -> HsMatchContext GhcRn
+        -> HsMatchContext GhcTc
         -> LPat GhcTc
         -> Type
         -> MatchResult CoreExpr
diff --git a/compiler/GHC/HsToCore/Match/Constructor.hs b/compiler/GHC/HsToCore/Match/Constructor.hs
index 03b212d0eef9..264f49e0ebca 100644
--- a/compiler/GHC/HsToCore/Match/Constructor.hs
+++ b/compiler/GHC/HsToCore/Match/Constructor.hs
@@ -21,7 +21,7 @@ import {-# SOURCE #-} GHC.HsToCore.Match ( match )
 import GHC.Hs
 import GHC.HsToCore.Binds
 import GHC.Core.ConLike
-import GHC.Types.Basic ( Origin(..) )
+import GHC.Types.Basic
 import GHC.Tc.Utils.TcType
 import GHC.Core.Multiplicity
 import GHC.HsToCore.Monad
@@ -168,7 +168,7 @@ matchOneConLike vars ty mult (eqn1 :| eqns)   -- All eqns for a single construct
                        return ( wrapBinds (tvs `zip` tvs1)
                               . wrapBinds (ds  `zip` dicts1)
                               . mkCoreLets ds_bind
-                              , eqn { eqn_orig = Generated
+                              , eqn { eqn_orig = Generated SkipPmc
                                     , eqn_pats = conArgPats val_arg_tys args ++ pats }
                               )
               shift (_, (EqnInfo { eqn_pats = ps })) = pprPanic "matchOneCon/shift" (ppr ps)
diff --git a/compiler/GHC/HsToCore/Monad.hs b/compiler/GHC/HsToCore/Monad.hs
index 2740e5dbec47..6ba19bb95892 100644
--- a/compiler/GHC/HsToCore/Monad.hs
+++ b/compiler/GHC/HsToCore/Monad.hs
@@ -124,7 +124,7 @@ import qualified Data.Set as S
 -}
 
 data DsMatchContext
-  = DsMatchContext (HsMatchContext GhcRn) SrcSpan
+  = DsMatchContext (HsMatchContext GhcTc) SrcSpan
   deriving ()
 
 instance Outputable DsMatchContext where
diff --git a/compiler/GHC/HsToCore/Pmc.hs b/compiler/GHC/HsToCore/Pmc.hs
index cd5bf9ddcd5a..aa72db0aed57 100644
--- a/compiler/GHC/HsToCore/Pmc.hs
+++ b/compiler/GHC/HsToCore/Pmc.hs
@@ -112,7 +112,7 @@ pmcPatBind _ _ _ = pure ()
 -- | Exhaustive for guard matches, is used for guards in pattern bindings and
 -- in @MultiIf@ expressions. Returns the 'Nablas' covered by the RHSs.
 pmcGRHSs
-  :: HsMatchContext GhcRn         -- ^ Match context, for warning messages
+  :: HsMatchContext GhcTc         -- ^ Match context, for warning messages
   -> GRHSs GhcTc (LHsExpr GhcTc)  -- ^ The GRHSs to check
   -> DsM (NonEmpty Nablas)        -- ^ Covered 'Nablas' for each RHS, for long
                                   --   distance info
diff --git a/compiler/GHC/HsToCore/Pmc/Utils.hs b/compiler/GHC/HsToCore/Pmc/Utils.hs
index 40ac5907f434..b39862821a50 100644
--- a/compiler/GHC/HsToCore/Pmc/Utils.hs
+++ b/compiler/GHC/HsToCore/Pmc/Utils.hs
@@ -14,7 +14,7 @@ module GHC.HsToCore.Pmc.Utils (
 
 import GHC.Prelude
 
-import GHC.Types.Basic (Origin(..), isGenerated)
+import GHC.Types.Basic (Origin(..), requiresPMC)
 import GHC.Driver.DynFlags
 import GHC.Hs
 import GHC.Core.Type
@@ -109,23 +109,20 @@ arrowMatchContextExhaustiveWarningFlag = \ case
 -- exhaustiveness check).
 isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext id -> Bool
 isMatchContextPmChecked dflags origin kind
-  | isGenerated origin
-  = False
-  | otherwise
-  = overlapping dflags kind || exhaustive dflags kind
+  =  requiresPMC origin
+  && (overlapping dflags kind || exhaustive dflags kind)
 
 -- | Return True when any of the pattern match warnings ('allPmCheckWarnings')
 -- are enabled, in which case we need to run the pattern match checker.
 needToRunPmCheck :: DynFlags -> Origin -> Bool
 needToRunPmCheck dflags origin
-  | isGenerated origin
-  = False
-  | otherwise
-  = notNull (filter (`wopt` dflags) allPmCheckWarnings)
+  =  requiresPMC origin
+  && notNull (filter (`wopt` dflags) allPmCheckWarnings)
 
 {- Note [Inaccessible warnings for record updates]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider (#12957)
+Consider (#12957):
+
   data T a where
     T1 :: { x :: Int } -> T Bool
     T2 :: { x :: Int } -> T a
@@ -134,8 +131,9 @@ Consider (#12957)
   f :: T Char -> T a
   f r = r { x = 3 }
 
-The desugarer will conservatively generate a case for T1 even though
-it's impossible:
+In GHC.Tc.Gen.Expr.desugarRecordUpd, we will conservatively generate a case
+for T1 even though it's impossible:
+
   f r = case r of
           T1 x -> T1 3   -- Inaccessible branch
           T2 x -> T2 3
@@ -143,13 +141,14 @@ it's impossible:
 
 We don't want to warn about the inaccessible branch because the programmer
 didn't put it there!  So we filter out the warning here.
+The test case T12957a checks this.
 
 The same can happen for long distance term constraints instead of type
 constraints (#17783):
 
-  data T = A { x :: Int } | B { x :: Int }
+  data T = A { x :: Int } | B
   f r@A{} = r { x = 3 }
-  f _     = B 0
+  f _     = B
 
 Here, the long distance info from the FunRhs match (@r ~ A x@) will make the
 clause matching on @B@ of the desugaring to @case@ redundant. It's generated
diff --git a/compiler/GHC/HsToCore/Utils.hs b/compiler/GHC/HsToCore/Utils.hs
index 85484cbb4e54..0f696d6b28d2 100644
--- a/compiler/GHC/HsToCore/Utils.hs
+++ b/compiler/GHC/HsToCore/Utils.hs
@@ -453,7 +453,7 @@ For uniformity, calls to 'error' in both cases are wrapped even if -XLinearTypes
 is disabled.
 -}
 
-mkFailExpr :: HsMatchContext GhcRn -> Type -> DsM CoreExpr
+mkFailExpr :: HsMatchContext GhcTc -> Type -> DsM CoreExpr
 mkFailExpr ctxt ty
   = mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt)
 
diff --git a/compiler/GHC/Iface/Ext/Ast.hs b/compiler/GHC/Iface/Ext/Ast.hs
index 3a7b8452aa53..a2578641ca90 100644
--- a/compiler/GHC/Iface/Ext/Ast.hs
+++ b/compiler/GHC/Iface/Ext/Ast.hs
@@ -890,7 +890,7 @@ instance ( HiePass p
 
 setOrigin :: Origin -> NodeOrigin -> NodeOrigin
 setOrigin FromSource _ = SourceInfo
-setOrigin Generated _ = GeneratedInfo
+setOrigin (Generated {}) _ = GeneratedInfo
 
 instance HiePass p => ToHie (Located (PatSynBind (GhcPass p) (GhcPass p))) where
     toHie (L sp psb) = concatM $ case psb of
diff --git a/compiler/GHC/Rename/Expr.hs b/compiler/GHC/Rename/Expr.hs
index 68b73d2b4830..2965d290126e 100644
--- a/compiler/GHC/Rename/Expr.hs
+++ b/compiler/GHC/Rename/Expr.hs
@@ -428,7 +428,7 @@ rnExpr (HsLamCase x lc_variant matches)
 rnExpr (HsCase _ expr matches)
   = do { (new_expr, e_fvs) <- rnLExpr expr
        ; (new_matches, ms_fvs) <- rnMatchGroup CaseAlt rnLExpr matches
-       ; return (HsCase noExtField new_expr new_matches, e_fvs `plusFV` ms_fvs) }
+       ; return (HsCase CaseAlt new_expr new_matches, e_fvs `plusFV` ms_fvs) }
 
 rnExpr (HsLet _ tkLet binds tkIn expr)
   = rnLocalBindsAndThen binds $ \binds' _ -> do
diff --git a/compiler/GHC/Rename/Utils.hs b/compiler/GHC/Rename/Utils.hs
index 81fb803e51fc..1b5049737296 100644
--- a/compiler/GHC/Rename/Utils.hs
+++ b/compiler/GHC/Rename/Utils.hs
@@ -56,7 +56,7 @@ import GHC.Types.SourceFile
 import GHC.Types.SourceText ( SourceText(..), IntegralLit )
 import GHC.Utils.Outputable
 import GHC.Utils.Misc
-import GHC.Types.Basic  ( TopLevelFlag(..), Origin(Generated), TypeOrKind )
+import GHC.Types.Basic
 import GHC.Data.List.SetOps ( removeDupsOn )
 import GHC.Data.Maybe ( whenIsJust )
 import GHC.Driver.DynFlags
@@ -628,7 +628,7 @@ genFunBind :: LocatedN Name -> [LMatch GhcRn (LHsExpr GhcRn)]
            -> HsBind GhcRn
 genFunBind fn ms
   = FunBind { fun_id = fn
-            , fun_matches = mkMatchGroup Generated (wrapGenSpan ms)
+            , fun_matches = mkMatchGroup (Generated SkipPmc) (wrapGenSpan ms)
             , fun_ext = emptyNameSet
             }
 
diff --git a/compiler/GHC/Tc/Deriv/Generate.hs b/compiler/GHC/Tc/Deriv/Generate.hs
index 62cb85dee294..c3b74ee67100 100644
--- a/compiler/GHC/Tc/Deriv/Generate.hs
+++ b/compiler/GHC/Tc/Deriv/Generate.hs
@@ -2302,7 +2302,7 @@ mkFunBindSE arity loc fun pats_and_exprs
 mkRdrFunBind :: LocatedN RdrName -> [LMatch GhcPs (LHsExpr GhcPs)]
              -> LHsBind GhcPs
 mkRdrFunBind fun@(L loc _fun_rdr) matches
-  = L (na2la loc) (mkFunBind Generated fun matches)
+  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches)
 
 -- | Make a function binding. If no equations are given, produce a function
 -- with the given arity that uses an empty case expression for the last
@@ -2330,7 +2330,7 @@ mkRdrFunBindEC :: Arity
                -> [LMatch GhcPs (LHsExpr GhcPs)]
                -> LHsBind GhcPs
 mkRdrFunBindEC arity catch_all fun@(L loc _fun_rdr) matches
-  = L (na2la loc) (mkFunBind Generated fun matches')
+  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches')
  where
    -- Catch-all eqn looks like
    --     fmap _ z = case z of {}
@@ -2354,7 +2354,7 @@ mkRdrFunBindEC arity catch_all fun@(L loc _fun_rdr) matches
 mkRdrFunBindSE :: Arity -> LocatedN RdrName ->
                     [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
 mkRdrFunBindSE arity fun@(L loc fun_rdr) matches
-  = L (na2la loc) (mkFunBind Generated fun matches')
+  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches')
  where
    -- Catch-all eqn looks like
    --     compare _ _ = error "Void compare"
diff --git a/compiler/GHC/Tc/Gen/Expr.hs b/compiler/GHC/Tc/Gen/Expr.hs
index 2953f1281f1b..faba45ca67e5 100644
--- a/compiler/GHC/Tc/Gen/Expr.hs
+++ b/compiler/GHC/Tc/Gen/Expr.hs
@@ -393,7 +393,7 @@ tcExpr (HsCase x scrut matches) res_ty
         ; matches' <- tcMatchesCase match_ctxt (Scaled mult scrut_ty) matches res_ty
         ; return (HsCase x scrut' matches') }
  where
-    match_ctxt = MC { mc_what = CaseAlt,
+    match_ctxt = MC { mc_what = x,
                       mc_body = tcBody }
 
 tcExpr (HsIf x pred b1 b2) res_ty
@@ -1259,7 +1259,8 @@ desugarRecordUpd record_expr possible_parents rbnds res_ty
              ds_expr = HsLet noExtField noHsTok let_binds noHsTok (L gen case_expr)
 
              case_expr :: HsExpr GhcRn
-             case_expr = HsCase noExtField record_expr (mkMatchGroup Generated (wrapGenSpan matches))
+             case_expr = HsCase RecUpd record_expr
+                       $ mkMatchGroup (Generated DoPmc) (wrapGenSpan matches)
              matches :: [LMatch GhcRn (LHsExpr GhcRn)]
              matches = map make_pat relevant_cons
 
diff --git a/compiler/GHC/Tc/Gen/Splice.hs b/compiler/GHC/Tc/Gen/Splice.hs
index 853b983e82ed..6a5132138930 100644
--- a/compiler/GHC/Tc/Gen/Splice.hs
+++ b/compiler/GHC/Tc/Gen/Splice.hs
@@ -1971,7 +1971,7 @@ lookupName is_type_name s
 getThSpliceOrigin :: TcM Origin
 getThSpliceOrigin = do
   warn <- goptM Opt_EnableThSpliceWarnings
-  if warn then return FromSource else return Generated
+  if warn then return FromSource else return (Generated SkipPmc)
 
 
 getThing :: TH.Name -> TcM TcTyThing
diff --git a/compiler/GHC/Tc/TyCl/Instance.hs b/compiler/GHC/Tc/TyCl/Instance.hs
index f0eddac776f1..308dececf1cd 100644
--- a/compiler/GHC/Tc/TyCl/Instance.hs
+++ b/compiler/GHC/Tc/TyCl/Instance.hs
@@ -1955,17 +1955,15 @@ through typing information everywhere in the algorithm that generates Ord
 instances in order to determine which cases were unreachable. This seems like
 a lot of work for minimal gain, so we have opted not to go for this approach.
 
-Instead, we take the much simpler approach of always disabling
--Winaccessible-code for derived code. To accomplish this, we do the following:
+Instead, we take the following approach:
 
-1. In tcMethods (which typechecks method bindings), disable
-   -Winaccessible-code.
+1. In tcMethods (which typechecks method bindings), use 'setInGeneratedCode'.
 2. When creating Implications during typechecking, record this flag
    (in ic_warn_inaccessible) at the time of creation.
 3. After typechecking comes error reporting, where GHC must decide how to
    report inaccessible code to the user, on an Implication-by-Implication
-   basis. If an Implication's DynFlags indicate that -Winaccessible-code was
-   disabled, then don't bother reporting it. That's it!
+   basis. If the ic_warn_inaccessible field of the Implication is False, then
+   we don't bother reporting it. That's it!
 -}
 
 ------------------------
@@ -2214,7 +2212,7 @@ mkDefMethBind loc dfun_id clas sel_id dm_name
                                       , tyConBinderForAllTyFlag tcb /= Inferred ]
               rhs  = foldl' mk_vta (nlHsVar dm_name) visible_inst_tys
               bind = L (noAnnSrcSpan loc)
-                    $ mkTopFunBind Generated fn
+                    $ mkTopFunBind (Generated SkipPmc) fn
                         [mkSimpleMatch (mkPrefixFunRhs fn) [] rhs]
 
         ; liftIO (putDumpFileMaybe logger Opt_D_dump_deriv "Filling in method body"
diff --git a/compiler/GHC/Tc/TyCl/PatSyn.hs b/compiler/GHC/Tc/TyCl/PatSyn.hs
index 25e9ebd8ca59..c34e9159cb58 100644
--- a/compiler/GHC/Tc/TyCl/PatSyn.hs
+++ b/compiler/GHC/Tc/TyCl/PatSyn.hs
@@ -812,17 +812,18 @@ tcPatSynMatcher (L loc ps_name) lpat prag_fn
                      then [mkHsCaseAlt lpat  cont']
                      else [mkHsCaseAlt lpat  cont',
                            mkHsCaseAlt lwpat fail']
+             gen = Generated SkipPmc
              body = mkLHsWrap (mkWpLet req_ev_binds) $
                     L (getLoc lpat) $
-                    HsCase noExtField (nlHsVar scrutinee) $
+                    HsCase PatSyn (nlHsVar scrutinee) $
                     MG{ mg_alts = L (l2l $ getLoc lpat) cases
-                      , mg_ext = MatchGroupTc [unrestricted pat_ty] res_ty Generated
+                      , mg_ext = MatchGroupTc [unrestricted pat_ty] res_ty gen
                       }
              body' = noLocA $
                      HsLam noExtField $
                      MG{ mg_alts = noLocA [mkSimpleMatch LambdaExpr
                                                          args body]
-                       , mg_ext = MatchGroupTc (map unrestricted [pat_ty, cont_ty, fail_ty]) res_ty Generated
+                       , mg_ext = MatchGroupTc (map unrestricted [pat_ty, cont_ty, fail_ty]) res_ty gen
                        }
              match = mkMatch (mkPrefixFunRhs (L loc (idName patsyn_id))) []
                              (mkHsLams (rr_tv:res_tv:univ_tvs)
@@ -830,7 +831,7 @@ tcPatSynMatcher (L loc ps_name) lpat prag_fn
                              (EmptyLocalBinds noExtField)
              mg :: MatchGroup GhcTc (LHsExpr GhcTc)
              mg = MG{ mg_alts = L (l2l $ getLoc match) [match]
-                    , mg_ext = MatchGroupTc [] res_ty Generated
+                    , mg_ext = MatchGroupTc [] res_ty gen
                     }
              matcher_arity = length req_theta + 3
              -- See Note [Pragmas for pattern synonyms]
@@ -963,7 +964,7 @@ tcPatSynBuilderBind prag_fn (PSB { psb_id = ps_lname@(L loc ps_name)
            Unidirectional -> panic "tcPatSynBuilderBind"
 
     mk_mg :: LHsExpr GhcRn -> MatchGroup GhcRn (LHsExpr GhcRn)
-    mk_mg body = mkMatchGroup Generated (noLocA [builder_match])
+    mk_mg body = mkMatchGroup (Generated SkipPmc) (noLocA [builder_match])
           where
             builder_args  = [L (na2la loc) (VarPat noExtField (L loc n))
                             | L loc n <- args]
diff --git a/compiler/GHC/Tc/TyCl/Utils.hs b/compiler/GHC/Tc/TyCl/Utils.hs
index 9c9d356a22d2..767db8a7f704 100644
--- a/compiler/GHC/Tc/TyCl/Utils.hs
+++ b/compiler/GHC/Tc/TyCl/Utils.hs
@@ -931,7 +931,7 @@ mkOneRecordSelector all_cons idDetails fl has_sel
     -- make the binding: sel (C2 { fld = x }) = x
     --                   sel (C7 { fld = x }) = x
     --    where cons_w_field = [C2,C7]
-    sel_bind = mkTopFunBind Generated sel_lname alts
+    sel_bind = mkTopFunBind (Generated SkipPmc) sel_lname alts
       where
         alts | is_naughty = [mkSimpleMatch (mkPrefixFunRhs sel_lname)
                                            [] unit_rhs]
diff --git a/compiler/GHC/Tc/Types/Constraint.hs b/compiler/GHC/Tc/Types/Constraint.hs
index 837dff6bb90f..807348170c48 100644
--- a/compiler/GHC/Tc/Types/Constraint.hs
+++ b/compiler/GHC/Tc/Types/Constraint.hs
@@ -1456,8 +1456,7 @@ data Implication
       ic_given_eqs :: HasGivenEqs,  -- Are there Given equalities here?
 
       ic_warn_inaccessible :: Bool,
-                                 -- True  <=> -Winaccessible-code is enabled
-                                 -- at construction. See
+                                 -- True <=> we should report inaccessible code
                                  -- Note [Avoid -Winaccessible-code when deriving]
                                  -- in GHC.Tc.TyCl.Instance
 
diff --git a/compiler/GHC/Tc/Utils/Monad.hs b/compiler/GHC/Tc/Utils/Monad.hs
index ecc8bca4a3a3..a9bcbbe8edb2 100644
--- a/compiler/GHC/Tc/Utils/Monad.hs
+++ b/compiler/GHC/Tc/Utils/Monad.hs
@@ -61,7 +61,8 @@ module GHC.Tc.Utils.Monad(
   addDependentFiles,
 
   -- * Error management
-  getSrcSpanM, setSrcSpan, setSrcSpanA, addLocM, addLocMA, inGeneratedCode,
+  getSrcSpanM, setSrcSpan, setSrcSpanA, addLocM, addLocMA,
+  inGeneratedCode, setInGeneratedCode,
   wrapLocM, wrapLocAM, wrapLocFstM, wrapLocFstMA, wrapLocSndM, wrapLocSndMA, wrapLocM_,
   wrapLocMA_,wrapLocMA,
   getErrsVar, setErrsVar,
@@ -979,11 +980,18 @@ setSrcSpan (RealSrcSpan loc _) thing_inside
 
 setSrcSpan loc@(UnhelpfulSpan _) thing_inside
   | isGeneratedSrcSpan loc
-  = updLclCtxt (\env -> env { tcl_in_gen_code = True }) thing_inside
+  = setInGeneratedCode thing_inside
 
   | otherwise
   = thing_inside
 
+-- | Mark the inner computation as being done inside generated code.
+--
+-- See Note [Error contexts in generated code]
+setInGeneratedCode :: TcRn a -> TcRn a
+setInGeneratedCode thing_inside =
+  updLclCtxt (\env -> env { tcl_in_gen_code = True }) thing_inside
+
 setSrcSpanA :: SrcSpanAnn' ann -> TcRn a -> TcRn a
 setSrcSpanA l = setSrcSpan (locA l)
 
@@ -1204,15 +1212,17 @@ problem.
 
 Note [Error contexts in generated code]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* setSrcSpan sets tc_in_gen_code to True if the SrcSpan is GeneratedSrcSpan,
+* setSrcSpan sets tcl_in_gen_code to True if the SrcSpan is GeneratedSrcSpan,
   and back to False when we get a useful SrcSpan
 
-* When tc_in_gen_code is True, addErrCtxt becomes a no-op.
+* When tcl_in_gen_code is True, addErrCtxt becomes a no-op.
 
 So typically it's better to do setSrcSpan /before/ addErrCtxt.
 
 See Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr for
-more discussion of this fancy footwork.
+more discussion of this fancy footwork, as well as
+Note [Generated code and pattern-match checking] in GHC.Types.Basic for the
+relation with pattern-match checks.
 -}
 
 getErrCtxt :: TcM [ErrCtxt]
diff --git a/compiler/GHC/Tc/Utils/TcMType.hs b/compiler/GHC/Tc/Utils/TcMType.hs
index 239b293a9150..4eba350def76 100644
--- a/compiler/GHC/Tc/Utils/TcMType.hs
+++ b/compiler/GHC/Tc/Utils/TcMType.hs
@@ -342,7 +342,10 @@ newImplication :: TcM Implication
 newImplication
   = do env <- getLclEnv
        warn_inaccessible <- woptM Opt_WarnInaccessibleCode
-       return (implicationPrototype (mkCtLocEnv env)) { ic_warn_inaccessible = warn_inaccessible }
+       let in_gen_code = lclEnvInGeneratedCode env
+       return $
+         (implicationPrototype (mkCtLocEnv env))
+           { ic_warn_inaccessible = warn_inaccessible && not in_gen_code }
 
 {-
 ************************************************************************
diff --git a/compiler/GHC/Types/Basic.hs b/compiler/GHC/Types/Basic.hs
index 6fd1d1d6cef3..e743276e0ee8 100644
--- a/compiler/GHC/Types/Basic.hs
+++ b/compiler/GHC/Types/Basic.hs
@@ -36,7 +36,7 @@ module GHC.Types.Basic (
         FunctionOrData(..),
 
         RecFlag(..), isRec, isNonRec, boolToRecFlag,
-        Origin(..), isGenerated,
+        Origin(..), isGenerated, DoPmc(..), requiresPMC,
 
         RuleName, pprRuleName,
 
@@ -583,17 +583,62 @@ instance Binary RecFlag where
 ************************************************************************
 -}
 
+-- | Was this piece of code user-written or generated by the compiler?
+--
+-- See Note [Generated code and pattern-match checking].
 data Origin = FromSource
-            | Generated
+            | Generated DoPmc
             deriving( Eq, Data )
 
 isGenerated :: Origin -> Bool
-isGenerated Generated = True
-isGenerated FromSource = False
+isGenerated Generated {} = True
+isGenerated FromSource   = False
 
 instance Outputable Origin where
-  ppr FromSource  = text "FromSource"
-  ppr Generated   = text "Generated"
+  ppr FromSource      = text "FromSource"
+  ppr (Generated pmc) = text "Generated" <+> ppr pmc
+
+-- | Whether to run pattern-match checks in generated code.
+--
+-- See Note [Generated code and pattern-match checking].
+data DoPmc = SkipPmc
+           | DoPmc
+           deriving( Eq, Data )
+
+instance Outputable DoPmc where
+  ppr SkipPmc     = text "SkipPmc"
+  ppr DoPmc       = text "DoPmc"
+
+-- | Does this 'Origin' require us to run pattern-match checking,
+-- or should we skip these checks?
+--
+-- See Note [Generated code and pattern-match checking].
+requiresPMC :: Origin -> Bool
+requiresPMC (Generated SkipPmc) = False
+requiresPMC _ = True
+
+{- Note [Generated code and pattern-match checking]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some parts of the compiler generate code that is then typechecked. For example:
+
+  - the HsExpansion mechanism described in Note [Rebindable syntax and HsExpansion]
+    in GHC.Hs.Expr,
+  - the deriving mechanism.
+
+It is usually the case that we want to avoid generating error messages that
+refer to generated code. The way this is handled is that we mark certain
+parts of the AST as being generated (using the Origin datatype); this is then
+used to set the tcl_in_gen_code flag in TcLclEnv, as explained in
+Note [Error contexts in generated code] in GHC.Tc.Utils.Monad.
+
+Being in generated code is usually taken to mean we should also skip doing
+pattern-match checking, but not always. For example, when desugaring a record
+update (as described in Note [Record Updates] in GHC.Tc.Gen.Expr), we still want
+to do pattern-match checking, in order to report incomplete record updates
+(failing to do so lead to #23250). So, for a 'Generated' 'Origin', we keep track
+of whether we should do pattern-match checks; see the calls of the requiresPMC
+function (e.g. isMatchContextPmChecked and needToRunPmCheck in GHC.HsToCore.Pmc.Utils).
+-}
 
 {-
 ************************************************************************
diff --git a/testsuite/tests/ghc-api/T18522-dbg-ppr.hs b/testsuite/tests/ghc-api/T18522-dbg-ppr.hs
index 60eae1442595..918b39eb90b6 100644
--- a/testsuite/tests/ghc-api/T18522-dbg-ppr.hs
+++ b/testsuite/tests/ghc-api/T18522-dbg-ppr.hs
@@ -44,7 +44,7 @@ main = do
                        forall (a :: k) (b :: j) ->
                        () |]
       let hs_t = fromRight (error "convertToHsType") $
-                 convertToHsType Generated noSrcSpan th_t
+                 convertToHsType (Generated SkipPmc) noSrcSpan th_t
       (messages, mres) <-
         tcRnType hsc_env SkolemiseFlexi True hs_t
       let (warnings, errors) = partitionMessages messages
diff --git a/testsuite/tests/pmcheck/should_compile/T12957a.stderr b/testsuite/tests/pmcheck/should_compile/T12957a.stderr
index ba301f227e0b..883277d7ad22 100644
--- a/testsuite/tests/pmcheck/should_compile/T12957a.stderr
+++ b/testsuite/tests/pmcheck/should_compile/T12957a.stderr
@@ -1,13 +1,7 @@
 
-T12957a.hs:25:35: warning: [GHC-40564] [-Winaccessible-code (in -Wdefault)]
-    • Inaccessible code in
-        a pattern with constructor: BFields :: [()] -> Fields B,
-        in a case alternative
-      Couldn't match type ‘A’ with ‘B’
-    • In a record update at field ‘list’,
-      with type constructor ‘Fields’
-      and data constructor ‘BFields’.
-      In the expression: emptyA {list = [a]}
-      In a record update at field ‘sFields’,
-      with type constructor ‘S’
-      and data constructor ‘S’.
+T12957a.hs:25:35: warning: [GHC-62161] [-Wincomplete-record-updates (in -Wall)]
+    Pattern match(es) are non-exhaustive
+    In a record update:
+        Patterns of type ‘Fields A’ not matched:
+            AFields
+            EmptyFields
diff --git a/testsuite/tests/pmcheck/should_compile/T17783.hs b/testsuite/tests/pmcheck/should_compile/T17783.hs
index 8ac92460007e..1b67ec1d9d54 100644
--- a/testsuite/tests/pmcheck/should_compile/T17783.hs
+++ b/testsuite/tests/pmcheck/should_compile/T17783.hs
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -Wincomplete-record-updates #-}
-
 module Bug where
 
 data PartialRec = No
@@ -7,3 +5,9 @@ data PartialRec = No
 
 update No = No
 update r@(Yes {}) = r { b = False }
+
+
+data T = A { x :: Int } | B
+
+f r@A{} = r { x = 3 }
+f _     = B
diff --git a/testsuite/tests/pmcheck/should_compile/T21360.hs b/testsuite/tests/pmcheck/should_compile/T21360.hs
index db517a35a96a..80a8afebde05 100644
--- a/testsuite/tests/pmcheck/should_compile/T21360.hs
+++ b/testsuite/tests/pmcheck/should_compile/T21360.hs
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -Wincomplete-record-updates #-}
-
 module T21360 where
 
 data Foo = A {a :: Int} | B deriving Show
diff --git a/testsuite/tests/pmcheck/should_compile/T23520.hs b/testsuite/tests/pmcheck/should_compile/T23520.hs
new file mode 100644
index 000000000000..768cec3b4a53
--- /dev/null
+++ b/testsuite/tests/pmcheck/should_compile/T23520.hs
@@ -0,0 +1,5 @@
+module T23520 where
+
+data T = T1 { x :: Bool } | T2
+
+f a = a { x = False }
diff --git a/testsuite/tests/pmcheck/should_compile/T23520.stderr b/testsuite/tests/pmcheck/should_compile/T23520.stderr
new file mode 100644
index 000000000000..c7de2a511f8c
--- /dev/null
+++ b/testsuite/tests/pmcheck/should_compile/T23520.stderr
@@ -0,0 +1,4 @@
+
+T23520.hs:5:7: warning: [GHC-62161] [-Wincomplete-record-updates (in -Wall)]
+    Pattern match(es) are non-exhaustive
+    In a record update: Patterns of type ‘T’ not matched: T2
diff --git a/testsuite/tests/pmcheck/should_compile/all.T b/testsuite/tests/pmcheck/should_compile/all.T
index 810c8acbd78c..f9470110a647 100644
--- a/testsuite/tests/pmcheck/should_compile/all.T
+++ b/testsuite/tests/pmcheck/should_compile/all.T
@@ -64,7 +64,7 @@ test('T17646', normal, compile, [overlapping_incomplete])
 test('T17703', normal, compile, [overlapping_incomplete])
 test('T17725', normal, compile, [overlapping_incomplete])
 test('T17729', normal, compile, [overlapping_incomplete])
-test('T17783', normal, compile, [overlapping_incomplete])
+test('T17783', normal, compile, [overlapping_incomplete+'-Wincomplete-record-updates'])
 test('T17836', collect_compiler_stats('bytes allocated',10), compile, [overlapping_incomplete])
 test('T17836b', collect_compiler_stats('bytes allocated',10), compile, [overlapping_incomplete])
 test('T17977', collect_compiler_stats('bytes allocated',10), compile, [overlapping_incomplete])
@@ -89,7 +89,8 @@ test('T19384', expect_broken(19384), compile, [overlapping_incomplete])
 test('T19622', normal, compile, [overlapping_incomplete])
 test('T20631', normal, compile, [overlapping_incomplete])
 test('T20642', normal, compile, [overlapping_incomplete])
-test('T21360', normal, compile, [overlapping_incomplete])
+test('T21360', normal, compile, [overlapping_incomplete+'-Wincomplete-record-updates'])
+test('T23520', normal, compile, [overlapping_incomplete+'-Wincomplete-record-updates'])
 
 # Other tests
 test('pmc001', [], compile, [overlapping_incomplete])
@@ -104,8 +105,8 @@ test('pmc009', [], compile, [overlapping_incomplete+'-package ghc'])
 test('T11245', [], compile, [overlapping_incomplete])
 test('T11336b', [], compile, [overlapping_incomplete])
 test('T12949', [],  compile, [overlapping_incomplete])
-test('T12957', [], compile, [overlapping_incomplete])
-test('T12957a', [], compile, [overlapping_incomplete+'-fdefer-type-errors'])
+test('T12957', [], compile, [overlapping_incomplete+'-Wincomplete-record-updates'])
+test('T12957a', [], compile, [overlapping_incomplete+'-fdefer-type-errors -Wincomplete-record-updates'])
 test('PmExprVars', [],  compile, [overlapping_incomplete])
 test('CyclicSubst', [],  compile, [overlapping_incomplete])
 test('CaseOfKnownCon', [], compile, [overlapping_incomplete])
diff --git a/testsuite/tests/typecheck/should_fail/T3323.stderr b/testsuite/tests/typecheck/should_fail/T3323.stderr
index cb2d52f21df0..ec0a41b97300 100644
--- a/testsuite/tests/typecheck/should_fail/T3323.stderr
+++ b/testsuite/tests/typecheck/should_fail/T3323.stderr
@@ -3,12 +3,12 @@ T3323.hs:18:7: error: [GHC-39999]
     • Could not deduce ‘GHC.IO.Device.RawIO dev0’
       from the context: (GHC.IO.Device.RawIO dev,
                          GHC.IO.Device.IODevice dev, GHC.IO.BufferedIO.BufferedIO dev,
-                         base-4.17.0.0:Data.Typeable.Internal.Typeable dev)
+                         base-4.18.0.0:Data.Typeable.Internal.Typeable dev)
         bound by a pattern with constructor:
                    Handle__ :: forall dev enc_state dec_state.
                                (GHC.IO.Device.RawIO dev, GHC.IO.Device.IODevice dev,
                                 GHC.IO.BufferedIO.BufferedIO dev,
-                                base-4.17.0.0:Data.Typeable.Internal.Typeable dev) =>
+                                base-4.18.0.0:Data.Typeable.Internal.Typeable dev) =>
                                dev
                                -> HandleType
                                -> GHC.IORef.IORef (GHC.IO.Buffer.Buffer GHC.Word.Word8)
@@ -23,7 +23,7 @@ T3323.hs:18:7: error: [GHC-39999]
                                -> Newline
                                -> Maybe (GHC.MVar.MVar Handle__)
                                -> Handle__,
-                 in a case alternative
+                 in a record update
         at T3323.hs:18:7-28
       The type variable ‘dev0’ is ambiguous
     • In a record update at field ‘haDevice’,
diff --git a/testsuite/tests/typecheck/should_run/Typeable1.stderr b/testsuite/tests/typecheck/should_run/Typeable1.stderr
index 17817ade2617..95adaf7b46ea 100644
--- a/testsuite/tests/typecheck/should_run/Typeable1.stderr
+++ b/testsuite/tests/typecheck/should_run/Typeable1.stderr
@@ -23,3 +23,9 @@ Typeable1.hs:22:5: error: [GHC-40564] [-Winaccessible-code (in -Wdefault), Werro
     • Relevant bindings include
         y :: TypeRep b2 (bound at Typeable1.hs:19:11)
         x :: TypeRep a2 (bound at Typeable1.hs:19:9)
+
+Typeable1.hs:22:5: error: [GHC-94210] [-Woverlapping-patterns (in -Wdefault), Werror=overlapping-patterns]
+    Pattern match has inaccessible right hand side
+    In a pattern binding in
+         a 'do' block:
+        App x y <- ...
diff --git a/utils/haddock b/utils/haddock
index 495c0655dcb9..b96241bad1cd 160000
--- a/utils/haddock
+++ b/utils/haddock
@@ -1 +1 @@
-Subproject commit 495c0655dcb9a9482054c5e48c0106f57f5ddb06
+Subproject commit b96241bad1cd59c65a89dab74e6cba114129e521
-- 
GitLab