diff --git a/compiler/GHC/Builtin/Names.hs b/compiler/GHC/Builtin/Names.hs
--- a/compiler/GHC/Builtin/Names.hs
+++ b/compiler/GHC/Builtin/Names.hs
@@ -256,7 +256,7 @@
         typeRepIdName,
         mkTrTypeName,
         mkTrConName,
-        mkTrAppName,
+        mkTrAppCheckedName,
         mkTrFunName,
         typeSymbolTypeRepName, typeNatTypeRepName, typeCharTypeRepName,
         trGhcPrimModuleName,
@@ -1376,7 +1376,7 @@
   , someTypeRepDataConName
   , mkTrTypeName
   , mkTrConName
-  , mkTrAppName
+  , mkTrAppCheckedName
   , mkTrFunName
   , typeRepIdName
   , typeNatTypeRepName
@@ -1391,7 +1391,7 @@
 typeRepIdName         = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "typeRep#")       typeRepIdKey
 mkTrTypeName          = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "mkTrType")       mkTrTypeKey
 mkTrConName           = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "mkTrCon")        mkTrConKey
-mkTrAppName           = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "mkTrApp")        mkTrAppKey
+mkTrAppCheckedName    = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "mkTrAppChecked") mkTrAppCheckedKey
 mkTrFunName           = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "mkTrFun")        mkTrFunKey
 typeNatTypeRepName    = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "typeNatTypeRep") typeNatTypeRepKey
 typeSymbolTypeRepName = varQual gHC_INTERNAL_TYPEABLE_INTERNAL (fsLit "typeSymbolTypeRep") typeSymbolTypeRepKey
@@ -2508,7 +2508,7 @@
 mkTyConKey
   , mkTrTypeKey
   , mkTrConKey
-  , mkTrAppKey
+  , mkTrAppCheckedKey
   , mkTrFunKey
   , typeNatTypeRepKey
   , typeSymbolTypeRepKey
@@ -2518,7 +2518,7 @@
 mkTyConKey            = mkPreludeMiscIdUnique 503
 mkTrTypeKey           = mkPreludeMiscIdUnique 504
 mkTrConKey            = mkPreludeMiscIdUnique 505
-mkTrAppKey            = mkPreludeMiscIdUnique 506
+mkTrAppCheckedKey     = mkPreludeMiscIdUnique 506
 typeNatTypeRepKey     = mkPreludeMiscIdUnique 507
 typeSymbolTypeRepKey  = mkPreludeMiscIdUnique 508
 typeCharTypeRepKey    = mkPreludeMiscIdUnique 509
diff --git a/compiler/GHC/Core/Predicate.hs b/compiler/GHC/Core/Predicate.hs
--- a/compiler/GHC/Core/Predicate.hs
+++ b/compiler/GHC/Core/Predicate.hs
@@ -27,7 +27,7 @@
   -- Implicit parameters
   isIPLikePred, mentionsIP, isIPTyCon, isIPClass,
   isCallStackTy, isCallStackPred, isCallStackPredTy,
-  isExceptionContextPred,
+  isExceptionContextPred, isExceptionContextTy,
   isIPPred_maybe,
 
   -- Evidence variables
@@ -39,7 +39,6 @@
 
 import GHC.Core.Type
 import GHC.Core.Class
-import GHC.Core.TyCo.Compare( eqType )
 import GHC.Core.TyCon
 import GHC.Core.TyCon.RecWalk
 import GHC.Types.Var
@@ -292,7 +291,7 @@
   | otherwise
   = Nothing
 
--- | Is a type a 'CallStack'?
+-- | Is a type an 'ExceptionContext'?
 isExceptionContextTy :: Type -> Bool
 isExceptionContextTy ty
   | Just tc <- tyConAppTyCon_maybe ty
@@ -338,31 +337,38 @@
 isIPLikePred :: Type -> Bool
 -- Is `pred`, or any of its superclasses, an implicit parameter?
 -- See Note [Local implicit parameters]
-isIPLikePred pred = mentions_ip_pred initIPRecTc Nothing pred
+isIPLikePred pred =
+  mentions_ip_pred initIPRecTc (const True) (const True) pred
 
-mentionsIP :: Type -> Class -> [Type] -> Bool
--- Is (cls tys) an implicit parameter with key `str_ty`, or
--- is any of its superclasses such at thing.
+mentionsIP :: (Type -> Bool) -- ^ predicate on the string
+           -> (Type -> Bool) -- ^ predicate on the type
+           -> Class
+           -> [Type] -> Bool
+-- ^ @'mentionsIP' str_cond ty_cond cls tys@ returns @True@ if:
+--
+--    - @cls tys@ is of the form @IP str ty@, where @str_cond str@ and @ty_cond ty@
+--      are both @True@,
+--    - or any superclass of @cls tys@ has this property.
+--
 -- See Note [Local implicit parameters]
-mentionsIP str_ty cls tys = mentions_ip initIPRecTc (Just str_ty) cls tys
+mentionsIP = mentions_ip initIPRecTc
 
-mentions_ip :: RecTcChecker -> Maybe Type -> Class -> [Type] -> Bool
-mentions_ip rec_clss mb_str_ty cls tys
-  | Just (str_ty', _) <- isIPPred_maybe cls tys
-  = case mb_str_ty of
-       Nothing -> True
-       Just str_ty -> str_ty `eqType` str_ty'
+mentions_ip :: RecTcChecker -> (Type -> Bool) -> (Type -> Bool) -> Class -> [Type] -> Bool
+mentions_ip rec_clss str_cond ty_cond cls tys
+  | Just (str_ty, ty) <- isIPPred_maybe cls tys
+  = str_cond str_ty && ty_cond ty
   | otherwise
-  = or [ mentions_ip_pred rec_clss mb_str_ty (classMethodInstTy sc_sel_id tys)
+  = or [ mentions_ip_pred rec_clss str_cond ty_cond (classMethodInstTy sc_sel_id tys)
        | sc_sel_id <- classSCSelIds cls ]
 
-mentions_ip_pred :: RecTcChecker -> Maybe Type -> Type -> Bool
-mentions_ip_pred  rec_clss mb_str_ty ty
+
+mentions_ip_pred :: RecTcChecker -> (Type -> Bool) -> (Type -> Bool) -> Type -> Bool
+mentions_ip_pred rec_clss str_cond ty_cond ty
   | Just (cls, tys) <- getClassPredTys_maybe ty
   , let tc = classTyCon cls
   , Just rec_clss' <- if isTupleTyCon tc then Just rec_clss
                       else checkRecTc rec_clss tc
-  = mentions_ip rec_clss' mb_str_ty cls tys
+  = mentions_ip rec_clss' str_cond ty_cond cls tys
   | otherwise
   = False -- Includes things like (D []) where D is
           -- a Constraint-ranged family; #7785
@@ -429,7 +435,38 @@
 * The superclass hunt stops when it encounters the same class again,
   but in principle we could have the same class, differently instantiated,
   and the second time it could have an implicit parameter
-I'm going to treat these as problems for another day. They are all exotic.  -}
+I'm going to treat these as problems for another day. They are all exotic.
+
+Note [Using typesAreApart when calling mentionsIP]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We call 'mentionsIP' in two situations:
+
+  (1) to check that a predicate does not contain any implicit parameters
+      IP str ty, for a fixed literal str and any type ty,
+  (2) to check that a predicate does not contain any HasCallStack or
+      HasExceptionContext constraints.
+
+In both of these cases, we want to be sure, so we should be conservative:
+
+  For (1), the predicate might contain an implicit parameter IP Str a, where
+  Str is a type family such as:
+
+    type family MyStr where MyStr = "abc"
+
+  To safeguard against this (niche) situation, instead of doing a simple
+  type equality check, we use 'typesAreApart'. This allows us to recognise
+  that 'IP MyStr a' contains an implicit parameter of the form 'IP "abc" ty'.
+
+  For (2), we similarly might have
+
+    type family MyCallStack where MyCallStack = CallStack
+
+  Again, here we use 'typesAreApart'. This allows us to see that
+
+    (?foo :: MyCallStack)
+
+  is indeed a CallStack constraint, hidden under a type family.
+-}
 
 {- *********************************************************************
 *                                                                      *
diff --git a/compiler/GHC/Core/TyCon.hs b/compiler/GHC/Core/TyCon.hs
--- a/compiler/GHC/Core/TyCon.hs
+++ b/compiler/GHC/Core/TyCon.hs
@@ -2659,6 +2659,7 @@
 tyConStupidTheta tc@(TyCon { tyConDetails = details })
   | AlgTyCon {algTcStupidTheta = stupid} <- details = stupid
   | PrimTyCon {} <- details                         = []
+  | PromotedDataCon {} <- details                   = []
   | otherwise = pprPanic "tyConStupidTheta" (ppr tc)
 
 -- | Extract the 'TyVar's bound by a vanilla type synonym
diff --git a/compiler/GHC/Driver/DynFlags.hs b/compiler/GHC/Driver/DynFlags.hs
--- a/compiler/GHC/Driver/DynFlags.hs
+++ b/compiler/GHC/Driver/DynFlags.hs
@@ -395,6 +395,7 @@
   unfoldingOpts         :: !UnfoldingOpts,
 
   maxWorkerArgs         :: Int,
+  maxForcedSpecArgs     :: Int,
 
   ghciHistSize          :: Int,
 
@@ -676,6 +677,8 @@
 
         unfoldingOpts = defaultUnfoldingOpts,
         maxWorkerArgs = 10,
+        maxForcedSpecArgs = 333,
+        -- 333 is fairly arbitrary, see Note [Forcing specialisation]:FS5
 
         ghciHistSize = 50, -- keep a log of length 50 by default
 
@@ -1203,7 +1206,6 @@
     ++ default_PIC platform
 
     ++ validHoleFitDefaults
-
 
     where platform = sTargetPlatform settings
 
diff --git a/compiler/GHC/Driver/Flags.hs b/compiler/GHC/Driver/Flags.hs
--- a/compiler/GHC/Driver/Flags.hs
+++ b/compiler/GHC/Driver/Flags.hs
@@ -299,6 +299,7 @@
    | Opt_CmmElimCommonBlocks
    | Opt_CmmControlFlow
    | Opt_AsmShortcutting
+   | Opt_InterModuleFarJumps
    | Opt_OmitYields
    | Opt_FunToThunk               -- deprecated
    | Opt_DictsStrict                     -- be strict in argument dictionaries
@@ -544,6 +545,7 @@
    , Opt_CmmSink
    , Opt_CmmElimCommonBlocks
    , Opt_AsmShortcutting
+   , Opt_InterModuleFarJumps
    , Opt_FunToThunk
    , Opt_DmdTxDictSel
    , Opt_Loopification
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -1814,6 +1814,8 @@
 
   , make_ord_flag defFlag "fmax-worker-args"
       (intSuffix (\n d -> d {maxWorkerArgs = n}))
+  , make_ord_flag defFlag "fmax-forced-spec-args"
+      (intSuffix (\n d -> d {maxForcedSpecArgs = n}))
   , make_ord_flag defGhciFlag "fghci-hist-size"
       (intSuffix (\n d -> d {ghciHistSize = n}))
   , make_ord_flag defGhcFlag "fmax-inline-alloc-size"
@@ -2453,6 +2455,7 @@
   flagSpec "gen-manifest"                     Opt_GenManifest,
   flagSpec "ghci-history"                     Opt_GhciHistory,
   flagSpec "ghci-leak-check"                  Opt_GhciLeakCheck,
+  flagSpec "inter-module-far-jumps"               Opt_InterModuleFarJumps,
   flagSpec "validate-ide-info"                Opt_ValidateHie,
   flagGhciSpec "local-ghci-history"           Opt_LocalGhciHistory,
   flagGhciSpec "no-it"                        Opt_NoIt,
diff --git a/compiler/GHC/Hs/ImpExp.hs b/compiler/GHC/Hs/ImpExp.hs
--- a/compiler/GHC/Hs/ImpExp.hs
+++ b/compiler/GHC/Hs/ImpExp.hs
@@ -257,7 +257,6 @@
 ieNames (IEThingAbs  _ (L _ n) _)      = [ieWrappedName n]
 ieNames (IEThingAll  _ (L _ n) _)      = [ieWrappedName n]
 ieNames (IEThingWith _ (L _ n) _ ns _) = ieWrappedName n : map (ieWrappedName . unLoc) ns
--- NB the above case does not include names of field selectors
 ieNames (IEModuleContents {})     = []
 ieNames (IEGroup          {})     = []
 ieNames (IEDoc            {})     = []
diff --git a/compiler/GHC/Prelude/Basic.hs b/compiler/GHC/Prelude/Basic.hs
--- a/compiler/GHC/Prelude/Basic.hs
+++ b/compiler/GHC/Prelude/Basic.hs
@@ -23,6 +23,8 @@
   ,module Bits
   ,shiftL, shiftR
   ,head, tail
+
+  , strictGenericLength
   ) where
 
 
@@ -126,3 +128,15 @@
 tail :: HasCallStack => [a] -> [a]
 tail = Prelude.tail
 {-# INLINE tail #-}
+
+{- |
+The 'genericLength' function defined in base can't be specialised due to the
+NOINLINE pragma.
+
+It is also not strict in the accumulator, and strictGenericLength is not exported.
+
+See #25706 for why it is important to use a strict, specialised version.
+
+-}
+strictGenericLength :: Num a => [x] -> a
+strictGenericLength = fromIntegral . length
diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs
--- a/compiler/GHC/Tc/Errors/Ppr.hs
+++ b/compiler/GHC/Tc/Errors/Ppr.hs
@@ -55,7 +55,7 @@
 import GHC.Core.InstEnv
 import GHC.Core.TyCo.Rep (Type(..))
 import GHC.Core.TyCo.Ppr (pprWithInvisibleBitsWhen, pprSourceTyCon,
-                          pprTyVars, pprWithTYPE, pprTyVar, pprTidiedType)
+                          pprTyVars, pprWithTYPE, pprTyVar, pprTidiedType, pprForAll)
 import GHC.Core.PatSyn ( patSynName, pprPatSynType )
 import GHC.Core.Predicate
 import GHC.Core.Type
@@ -1299,24 +1299,27 @@
       text "Orphan COMPLETE pragmas not supported" $$
       text "A COMPLETE pragma must mention at least one data constructor" $$
       text "or pattern synonym defined in the same module."
-    TcRnEmptyCase ctxt -> mkSimpleDecorated message
-      where
-        pp_ctxt = case ctxt of
-          CaseAlt                                -> text "case expression"
-          LamAlt LamCase                         -> text "\\case expression"
-          ArrowMatchCtxt (ArrowLamAlt LamSingle) -> text "kappa abstraction"
-          ArrowMatchCtxt (ArrowLamAlt LamCase)   -> text "\\case command"
-          ArrowMatchCtxt ArrowCaseAlt            -> text "case command"
-          _                                      -> text "(unexpected)"
-                                                    <+> pprMatchContextNoun ctxt
-
-        message = case ctxt of
-          LamAlt LamCases -> lcases_msg <+> text "expression"
-          ArrowMatchCtxt (ArrowLamAlt LamCases) -> lcases_msg <+> text "command"
-          _ -> text "Empty list of alternatives in" <+> pp_ctxt
-
-        lcases_msg =
-          text "Empty list of alternatives is not allowed in \\cases"
+    TcRnEmptyCase ctxt reason -> mkSimpleDecorated $
+      case reason of
+        EmptyCaseWithoutFlag ->
+          text "Empty list of alternatives in" <+> pp_ctxt
+        EmptyCaseDisallowedCtxt ->
+          text "Empty list of alternatives is not allowed in" <+> pp_ctxt
+        EmptyCaseForall tvb ->
+          vcat [ text "Empty list of alternatives in" <+> pp_ctxt
+               , hang (text "checked against a forall-type:")
+                      2 (pprForAll [tvb] <+> text "...")
+               ]
+        where
+          pp_ctxt = case ctxt of
+            CaseAlt                                -> text "case expression"
+            LamAlt LamCase                         -> text "\\case expression"
+            LamAlt LamCases                        -> text "\\cases expression"
+            ArrowMatchCtxt (ArrowLamAlt LamSingle) -> text "kappa abstraction"
+            ArrowMatchCtxt (ArrowLamAlt LamCase)   -> text "\\case command"
+            ArrowMatchCtxt (ArrowLamAlt LamCases)  -> text "\\cases command"
+            ArrowMatchCtxt ArrowCaseAlt            -> text "case command"
+            ctxt                                   -> text "(unexpected)" <+> pprMatchContextNoun ctxt
     TcRnNonStdGuards (NonStandardGuards guards) -> mkSimpleDecorated $
       text "accepting non-standard pattern guards" $$
       nest 4 (interpp'SP guards)
@@ -2988,10 +2991,11 @@
       -> noHints
     TcRnOrphanCompletePragma{}
       -> noHints
-    TcRnEmptyCase ctxt -> case ctxt of
-      LamAlt LamCases -> noHints -- cases syntax doesn't support empty case.
-      ArrowMatchCtxt (ArrowLamAlt LamCases) -> noHints
-      _ -> [suggestExtension LangExt.EmptyCase]
+    TcRnEmptyCase _ reason ->
+      case reason of
+        EmptyCaseWithoutFlag{}    -> [suggestExtension LangExt.EmptyCase]
+        EmptyCaseDisallowedCtxt{} -> noHints
+        EmptyCaseForall{}         -> noHints
     TcRnNonStdGuards{}
       -> [suggestExtension LangExt.PatternGuards]
     TcRnDuplicateSigDecl{}
diff --git a/compiler/GHC/Tc/Errors/Types.hs b/compiler/GHC/Tc/Errors/Types.hs
--- a/compiler/GHC/Tc/Errors/Types.hs
+++ b/compiler/GHC/Tc/Errors/Types.hs
@@ -103,6 +103,7 @@
   , DisabledClassExtension(..)
   , TyFamsDisabledReason(..)
   , TypeApplication(..)
+  , BadEmptyCaseReason(..)
   , HsTypeOrSigType(..)
   , HsTyVarBndrExistentialFlag(..)
   , TySynCycleTyCons
@@ -204,7 +205,8 @@
 import GHC.Core.PatSyn (PatSyn)
 import GHC.Core.Predicate (EqRel, predTypeEqRel)
 import GHC.Core.TyCon (TyCon, Role, FamTyConFlav, AlgTyConRhs)
-import GHC.Core.Type (Kind, Type, ThetaType, PredType, ErrorMsgType, ForAllTyFlag)
+import GHC.Core.Type (Kind, Type, ThetaType, PredType, ErrorMsgType, ForAllTyFlag, ForAllTyBinder)
+
 import GHC.Driver.Backend (Backend)
 import GHC.Unit.State (UnitState)
 import GHC.Utils.Misc (filterOut)
@@ -3005,13 +3007,27 @@
       a case expression with an empty list of alternatives without
       enabling the EmptyCase extension.
 
-     Example(s):
+     Example for EmptyCaseWithoutFlag:
 
-       case () of
+       {-# LANGUAGE NoEmptyCase #-}
+       f :: Void -> a
+       f = \case {}    -- extension not enabled
 
+     Example for EmptyCaseDisallowedCtxt:
+
+       f = \cases {}   -- multi-case requires n>0 alternatives
+
+     Example for EmptyCaseForall:
+
+       f :: forall (xs :: Type) -> ()
+       f = \case {}    -- can't match on a type argument
+
      Test cases: rename/should_fail/RnEmptyCaseFail
+                 typecheck/should_fail/T25004
   -}
-  TcRnEmptyCase :: HsMatchContextRn -> TcRnMessage
+  TcRnEmptyCase :: !HsMatchContextRn
+                -> !BadEmptyCaseReason
+                -> TcRnMessage
 
   {-| TcRnNonStdGuards is a warning thrown when a user uses
       non-standard guards (e.g. patterns in guards) without
@@ -6082,6 +6098,12 @@
   = TypeApplication !(HsType GhcPs) !TypeOrKind
   | TypeApplicationInPattern !(HsConPatTyArg GhcPs)
   deriving Generic
+
+-- | Why was the empty case rejected?
+data BadEmptyCaseReason
+  = EmptyCaseWithoutFlag
+  | EmptyCaseDisallowedCtxt
+  | EmptyCaseForall ForAllTyBinder
 
 -- | Either `HsType p` or `HsSigType p`.
 --
diff --git a/compiler/GHC/Tc/Solver/Types.hs b/compiler/GHC/Tc/Solver/Types.hs
--- a/compiler/GHC/Tc/Solver/Types.hs
+++ b/compiler/GHC/Tc/Solver/Types.hs
@@ -166,7 +166,7 @@
     IP "callStack" CallStack
   See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence
 
-* We cannonicalise such constraints, in GHC.Tc.Solver.Dict.canDictNC, by
+* We canonicalise such constraints, in GHC.Tc.Solver.Dict.canDictNC, by
   pushing the call-site info on the stack, and changing the CtOrigin
   to record that has been done.
    Bind:  s1 = pushCallStack <site-info> s2
diff --git a/compiler/GHC/Types/Id/Make.hs b/compiler/GHC/Types/Id/Make.hs
--- a/compiler/GHC/Types/Id/Make.hs
+++ b/compiler/GHC/Types/Id/Make.hs
@@ -1535,39 +1535,87 @@
 
 
 
--- Given a type already assumed to have been normalized by topNormaliseType,
--- unpackable_type_datacons ty = Just datacons
--- iff ty is of the form
---     T ty1 .. tyn
--- and T is an algebraic data type (not newtype), in which no data
--- constructors have existentials, and datacons is the list of data
--- constructors of T.
 unpackable_type_datacons :: Type -> Maybe [DataCon]
+-- Given a type already assumed to have been normalized by topNormaliseType,
+--    unpackable_type_datacons (T ty1 .. tyn) = Just datacons
+-- iff the type can be unpacked (see Note [Unpacking GADTs and existentials])
+-- and `datacons` are the data constructors of T
 unpackable_type_datacons ty
   | Just (tc, _) <- splitTyConApp_maybe ty
-  , not (isNewTyCon tc)  -- Even though `ty` has been normalised, it could still
-                         -- be a /recursive/ newtype, so we must check for that
+  , not (isNewTyCon tc)
+      -- isNewTyCon: even though `ty` has been normalised, whic includes looking
+      -- through newtypes, it could still be a /recursive/ newtype, so we must
+      -- check for that case
   , Just cons <- tyConDataCons_maybe tc
-  , not (null cons)      -- Don't upack nullary sums; no need.
-                         -- They already take zero bits
-  , all (null . dataConExTyCoVars) cons
-  = Just cons -- See Note [Unpacking GADTs and existentials]
+  , unpackable_cons cons
+  = Just cons
   | otherwise
   = Nothing
+  where
+    unpackable_cons :: [DataCon] -> Bool
+    -- True if we can unpack a value of type (T t1 .. tn),
+    -- where T is an algebraic data type with these constructors
+    -- See Note [Unpacking GADTs and existentials]
+    unpackable_cons []   -- Don't unpack nullary sums; no need.
+      = False            -- They already take zero bits; see (UC0)
 
+    unpackable_cons [con]   -- Exactly one data constructor; see (UC1)
+      = null (dataConExTyCoVars con)
+
+    unpackable_cons cons  -- More than one data constructor; see (UC2)
+      = all isVanillaDataCon cons
+
 {-
 Note [Unpacking GADTs and existentials]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There is nothing stopping us unpacking a data type with equality
-components, like
-  data Equal a b where
-    Equal :: Equal a a
+Can we unpack a value of an algebraic data type T? For example
+   data D a = MkD {-# UNPACK #-} (T a)
+Can we unpack that (T a) field?
 
-And it'd be fine to unpack a product type with existential components
-too, but that would require a bit more plumbing, so currently we don't.
+Three cases to consider in `unpackable_cons`
 
-So for now we require: null (dataConExTyCoVars data_con)
-See #14978
+(UC0) No data constructors; a nullary sum type.  This already takes zero
+      bits so there is no point in unpacking it.
+
+(UC1) Single-constructor types (products).  We can just represent it by
+   its fields. For example, if `T` is defined as:
+      data T a = MkT a a Int
+   then we can unpack it as follows.  The worker for MkD takes three unpacked fields:
+       data D a = MkD a a Int
+       $MkD :: T a -> D a
+       $MkD (MkT a1 a2 i) = MkD a1 a2 i
+
+   We currently /can't/ do this if T has existentially-bound type variables,
+   hence:   null (dataConExTyCoVars con)   in `unpackable_cons`.
+   But see also (UC3) below.
+
+   But we /can/ do it for (some) GADTs, such as:
+      data Equal a b where { Equal :: Equal a a }
+      data Wom a where { Wom1 :: Int -> Wom Bool }
+   We will get a MkD constructor that includes some coercion arguments,
+   but that is fine.   See #14978.  We still can't accommodate existentials,
+   but these particular examples don't use existentials.
+
+(UC2) Multi-constructor types, e.g.
+        data T a = T1 a | T2 Int a
+  Here we unpack the field to an unboxed sum type, thus:
+    data D a = MkD (# a | (# Int, a #) #)
+
+  However, now we can't deal with GADTs at all, because we'd need an
+  unboxed sum whose component was a unboxed tuple, whose component(s)
+  have kind (CONSTRAINT r); and that's not well-kinded.  Hence the
+    all isVanillaDataCon
+  condition in `unpackable_cons`. See #25672.
+
+(UC3)  For single-constructor types, with some more plumbing we could
+   allow existentials. e.g.
+       data T a = forall b. MkT a (b->Int) b
+   could unpack to
+       data D a = forall b. MkD a (b->Int) b
+       $MkD :: T a -> D a
+       $MkD (MkT @b x f y) = MkD @b x f y
+   Eminently possible, but more plumbing needed.
+
 
 Note [Unpack one-wide fields]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/ghc.cabal b/compiler/ghc.cabal
--- a/compiler/ghc.cabal
+++ b/compiler/ghc.cabal
@@ -3,7 +3,7 @@
 -- ./configure.  Make sure you are editing ghc.cabal.in, not ghc.cabal.
 
 Name: ghc
-Version: 9.10.2
+Version: 9.10.3
 License: BSD-3-Clause
 License-File: LICENSE
 Author: The GHC Team
@@ -121,9 +121,9 @@
                    exceptions == 0.10.*,
                    semaphore-compat,
                    stm,
-                   ghc-boot   == 9.10.2,
-                   ghc-heap   == 9.10.2,
-                   ghci == 9.10.2
+                   ghc-boot   == 9.10.3,
+                   ghc-heap   == 9.10.3,
+                   ghci == 9.10.3
 
     if os(windows)
         Build-Depends: Win32  >= 2.3 && < 2.15
diff --git a/ghc-lib-parser.cabal b/ghc-lib-parser.cabal
--- a/ghc-lib-parser.cabal
+++ b/ghc-lib-parser.cabal
@@ -1,7 +1,7 @@
 cabal-version: 3.0
 build-type: Simple
 name: ghc-lib-parser
-version: 9.10.2.20250515
+version: 9.10.3.20250912
 license: BSD-3-Clause
 license-file: LICENSE
 category: Development
diff --git a/ghc-lib/stage0/compiler/build/GHC/Settings/Config.hs b/ghc-lib/stage0/compiler/build/GHC/Settings/Config.hs
--- a/ghc-lib/stage0/compiler/build/GHC/Settings/Config.hs
+++ b/ghc-lib/stage0/compiler/build/GHC/Settings/Config.hs
@@ -22,10 +22,10 @@
 cProjectName          = "The Glorious Glasgow Haskell Compilation System"
 
 cBooterVersion        :: String
-cBooterVersion        = "9.10.2"
+cBooterVersion        = "9.10.1"
 
 cStage                :: String
 cStage                = show (1 :: Int)
 
 cProjectUnitId :: String
-cProjectUnitId = "ghc-9.10.2-inplace"
+cProjectUnitId = "ghc-9.10.3-inplace"
diff --git a/ghc-lib/stage0/lib/settings b/ghc-lib/stage0/lib/settings
--- a/ghc-lib/stage0/lib/settings
+++ b/ghc-lib/stage0/lib/settings
@@ -17,14 +17,14 @@
 ,("ld supports filelist", "YES")
 ,("ld supports single module", "NO")
 ,("ld is GNU ld", "NO")
-,("Merge objects command", "/usr/bin/ld")
+,("Merge objects command", "/usr/local/anaconda3/bin/ld")
 ,("Merge objects flags", "-r")
 ,("Merge objects supports response files", "YES")
-,("ar command", "/usr/bin/ar")
+,("ar command", "/usr/local/anaconda3/bin/ar")
 ,("ar flags", "qcls")
 ,("ar supports at file", "NO")
 ,("ar supports -L", "NO")
-,("ranlib command", "/usr/bin/ranlib")
+,("ranlib command", "/usr/local/anaconda3/bin/ranlib")
 ,("otool command", "otool")
 ,("install_name_tool command", "install_name_tool")
 ,("windres command", "/bin/false")
diff --git a/ghc-lib/stage0/libraries/ghc-boot/build/GHC/Version.hs b/ghc-lib/stage0/libraries/ghc-boot/build/GHC/Version.hs
--- a/ghc-lib/stage0/libraries/ghc-boot/build/GHC/Version.hs
+++ b/ghc-lib/stage0/libraries/ghc-boot/build/GHC/Version.hs
@@ -3,19 +3,19 @@
 import Prelude -- See Note [Why do we import Prelude here?]
 
 cProjectGitCommitId   :: String
-cProjectGitCommitId   = "c9de16b57adcb6810d059ebd1c72d97b4b6a7cec"
+cProjectGitCommitId   = "3f4d7d38b9661435bdde981451ac50c4335ed090"
 
 cProjectVersion       :: String
-cProjectVersion       = "9.10.2"
+cProjectVersion       = "9.10.3"
 
 cProjectVersionInt    :: String
 cProjectVersionInt    = "910"
 
 cProjectPatchLevel    :: String
-cProjectPatchLevel    = "2"
+cProjectPatchLevel    = "3"
 
 cProjectPatchLevel1   :: String
-cProjectPatchLevel1   = "2"
+cProjectPatchLevel1   = "3"
 
 cProjectPatchLevel2   :: String
 cProjectPatchLevel2   = "0"
diff --git a/ghc/ghc-bin.cabal b/ghc/ghc-bin.cabal
--- a/ghc/ghc-bin.cabal
+++ b/ghc/ghc-bin.cabal
@@ -2,7 +2,7 @@
 -- ./configure.  Make sure you are editing ghc-bin.cabal.in, not ghc-bin.cabal.
 
 Name: ghc-bin
-Version: 9.10.2
+Version: 9.10.3
 Copyright: XXX
 -- License: XXX
 -- License-File: XXX
@@ -39,8 +39,8 @@
                    filepath   >= 1   && < 1.6,
                    containers >= 0.5 && < 0.8,
                    transformers >= 0.5 && < 0.7,
-                   ghc-boot      == 9.10.2,
-                   ghc           == 9.10.2
+                   ghc-boot      == 9.10.3,
+                   ghc           == 9.10.3
 
     if os(windows)
         Build-Depends: Win32  >= 2.3 && < 2.15
@@ -58,7 +58,7 @@
         Build-depends:
             deepseq        >= 1.4 && < 1.6,
             ghc-prim       >= 0.5.0 && < 0.13,
-            ghci           == 9.10.2,
+            ghci           == 9.10.3,
             haskeline      == 0.8.*,
             exceptions     == 0.10.*,
             time           >= 1.8 && < 1.13
diff --git a/libraries/ghc-boot-th/ghc-boot-th.cabal b/libraries/ghc-boot-th/ghc-boot-th.cabal
--- a/libraries/ghc-boot-th/ghc-boot-th.cabal
+++ b/libraries/ghc-boot-th/ghc-boot-th.cabal
@@ -3,7 +3,7 @@
 -- ghc-boot-th.cabal.in, not ghc-boot-th.cabal.
 
 name:           ghc-boot-th
-version:        9.10.2
+version:        9.10.3
 license:        BSD3
 license-file:   LICENSE
 category:       GHC
diff --git a/libraries/ghc-boot/GHC/Data/SizedSeq.hs b/libraries/ghc-boot/GHC/Data/SizedSeq.hs
--- a/libraries/ghc-boot/GHC/Data/SizedSeq.hs
+++ b/libraries/ghc-boot/GHC/Data/SizedSeq.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE StandaloneDeriving, DeriveGeneric #-}
+{-# LANGUAGE StandaloneDeriving, DeriveGeneric, CPP #-}
 module GHC.Data.SizedSeq
   ( SizedSeq(..)
   , emptySS
@@ -11,9 +11,12 @@
 import Prelude -- See note [Why do we import Prelude here?]
 import Control.DeepSeq
 import Data.Binary
-import Data.List (genericLength)
 import GHC.Generics
 
+#if ! MIN_VERSION_base(4,20,0)
+import Data.List (foldl')
+#endif
+
 data SizedSeq a = SizedSeq {-# UNPACK #-} !Word [a]
   deriving (Generic, Show)
 
@@ -37,9 +40,9 @@
 addToSS :: SizedSeq a -> a -> SizedSeq a
 addToSS (SizedSeq n r_xs) x = SizedSeq (n+1) (x:r_xs)
 
+-- NB, important this is eta-expand so that foldl' is inlined.
 addListToSS :: SizedSeq a -> [a] -> SizedSeq a
-addListToSS (SizedSeq n r_xs) xs
-  = SizedSeq (n + genericLength xs) (reverse xs ++ r_xs)
+addListToSS s xs = foldl' addToSS s xs
 
 ssElts :: SizedSeq a -> [a]
 ssElts (SizedSeq _ r_xs) = reverse r_xs
diff --git a/libraries/ghc-boot/ghc-boot.cabal b/libraries/ghc-boot/ghc-boot.cabal
--- a/libraries/ghc-boot/ghc-boot.cabal
+++ b/libraries/ghc-boot/ghc-boot.cabal
@@ -5,7 +5,7 @@
 -- ghc-boot.cabal.
 
 name:           ghc-boot
-version:        9.10.2
+version:        9.10.3
 license:        BSD-3-Clause
 license-file:   LICENSE
 category:       GHC
@@ -81,7 +81,7 @@
                    filepath   >= 1.3 && < 1.6,
                    deepseq    >= 1.4 && < 1.6,
                    ghc-platform >= 0.1,
-                   ghc-boot-th == 9.10.2
+                   ghc-boot-th == 9.10.3
     if !os(windows)
         build-depends:
                    unix       >= 2.7 && < 2.9
diff --git a/libraries/ghc-heap/ghc-heap.cabal b/libraries/ghc-heap/ghc-heap.cabal
--- a/libraries/ghc-heap/ghc-heap.cabal
+++ b/libraries/ghc-heap/ghc-heap.cabal
@@ -1,6 +1,6 @@
 cabal-version:  3.0
 name:           ghc-heap
-version:        9.10.2
+version:        9.10.3
 license:        BSD-3-Clause
 license-file:   LICENSE
 maintainer:     libraries@haskell.org
@@ -28,7 +28,7 @@
                   , containers       >= 0.6.2.1 && < 0.8
 
   if impl(ghc >= 9.9)
-    build-depends:  ghc-internal     >= 9.900 && < 9.1002.99999
+    build-depends:  ghc-internal     >= 9.900 && < 9.1003.99999
 
   ghc-options:      -Wall
   if !os(ghcjs)
diff --git a/libraries/ghci/GHCi/Message.hs b/libraries/ghci/GHCi/Message.hs
--- a/libraries/ghci/GHCi/Message.hs
+++ b/libraries/ghci/GHCi/Message.hs
@@ -493,7 +493,7 @@
 #define MIN_VERSION_ghc_heap(major1,major2,minor) (\
   (major1) <  9 || \
   (major1) == 9 && (major2) <  10 || \
-  (major1) == 9 && (major2) == 10 && (minor) <= 2)
+  (major1) == 9 && (major2) == 10 && (minor) <= 3)
 #endif /* MIN_VERSION_ghc_heap */
 #if MIN_VERSION_ghc_heap(8,11,0)
 instance Binary Heap.StgTSOProfInfo
diff --git a/libraries/ghci/ghci.cabal b/libraries/ghci/ghci.cabal
--- a/libraries/ghci/ghci.cabal
+++ b/libraries/ghci/ghci.cabal
@@ -2,7 +2,7 @@
 -- ../../configure.  Make sure you are editing ghci.cabal.in, not ghci.cabal.
 
 name:           ghci
-version:        9.10.2
+version:        9.10.3
 license:        BSD3
 license-file:   LICENSE
 category:       GHC
@@ -82,8 +82,8 @@
         containers       >= 0.5 && < 0.8,
         deepseq          >= 1.4 && < 1.6,
         filepath         >= 1.4 && < 1.6,
-        ghc-boot         == 9.10.2,
-        ghc-heap         == 9.10.2,
+        ghc-boot         == 9.10.3,
+        ghc-heap         == 9.10.3,
         template-haskell == 2.22.*,
         transformers     >= 0.5 && < 0.7
 
diff --git a/libraries/template-haskell/template-haskell.cabal b/libraries/template-haskell/template-haskell.cabal
--- a/libraries/template-haskell/template-haskell.cabal
+++ b/libraries/template-haskell/template-haskell.cabal
@@ -56,7 +56,7 @@
 
     build-depends:
         base        >= 4.11 && < 4.21,
-        ghc-boot-th == 9.10.2,
+        ghc-boot-th == 9.10.3,
         ghc-prim,
         pretty      == 1.1.*
 
