Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC

Commits:

25 changed files:

Changes:

  • compiler/GHC/Builtin/Types/Prim.hs
    ... ... @@ -752,8 +752,9 @@ Specifically (a ~# b) :: CONSTRAINT (TupleRep [])
    752 752
     
    
    753 753
     Wrinkles
    
    754 754
     
    
    755
    -(W1) Type and Constraint are considered distinct throughout GHC. But they
    
    756
    -     are not /apart/: see Note [Type and Constraint are not apart]
    
    755
    +(W1) Type and Constraint are considered distinct throughout GHC.
    
    756
    +     That wasn't always the case:
    
    757
    +          see Historical Note [Type and Constraint are not apart]
    
    757 758
     
    
    758 759
     (W2) We need two absent-error Ids, aBSENT_ERROR_ID for types of kind Type, and
    
    759 760
          aBSENT_CONSTRAINT_ERROR_ID for types of kind Constraint.
    
    ... ... @@ -768,8 +769,24 @@ Wrinkles
    768 769
          of type TYPE rr. See (CPR2) in Note [Which types are unboxed?] in
    
    769 770
          GHC.Core.Opt.WorkWrap.Utils.
    
    770 771
     
    
    771
    -Note [Type and Constraint are not apart]
    
    772
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    772
    +-------------------------------------------------------------
    
    773
    +Historical Note [Type and Constraint are not apart]
    
    774
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    775
    +Nov 2025:
    
    776
    +  In the past, Type and Constraint were carefully coonsiderd to be
    
    777
    +  not /apart/.  But the necessity for that vanished with unary classes
    
    778
    +  (see Note [Unary class magic]), done in
    
    779
    +
    
    780
    +     commit 9bd7fcc518111a1549c98720c222cdbabd32ed46
    
    781
    +     Author: Simon Peyton Jones <simon.peytonjones@gmail.com>
    
    782
    +     Date:   Tue Apr 15 17:43:46 2025 +0100
    
    783
    +     Implement unary classes
    
    784
    +
    
    785
    +  So now Type and Constraint are simply distinct type constructors, just as
    
    786
    +  much as Int and Bool.
    
    787
    +
    
    788
    +  The rest of this Note is preserved for historical interest.
    
    789
    +
    
    773 790
     Type and Constraint are not equal (eqType) but they are not /apart/
    
    774 791
     either. Reason (c.f. #7451):
    
    775 792
     
    
    ... ... @@ -841,6 +858,9 @@ Wrinkles
    841 858
          So in GHC.Tc.Instance.Class.matchTypeable, Type and Constraint are
    
    842 859
          treated as separate TyCons; i.e. given no special treatment.
    
    843 860
     
    
    861
    +End of Historical Note
    
    862
    +-------------------------------------------------------------
    
    863
    +
    
    844 864
     Note [RuntimeRep polymorphism]
    
    845 865
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    846 866
     Generally speaking, you can't be polymorphic in `RuntimeRep`.  E.g
    

  • compiler/GHC/Core/Coercion.hs
    ... ... @@ -641,11 +641,6 @@ eqTyConRole tc
    641 641
     
    
    642 642
     -- | Given a coercion `co :: (t1 :: TYPE r1) ~ (t2 :: TYPE r2)`
    
    643 643
     -- produce a coercion `rep_co :: r1 ~ r2`
    
    644
    --- But actually it is possible that
    
    645
    ---     co :: (t1 :: CONSTRAINT r1) ~ (t2 :: CONSTRAINT r2)
    
    646
    --- or  co :: (t1 :: TYPE r1)       ~ (t2 :: CONSTRAINT r2)
    
    647
    --- or  co :: (t1 :: CONSTRAINT r1) ~ (t2 :: TYPE r2)
    
    648
    --- See Note [mkRuntimeRepCo]
    
    649 644
     mkRuntimeRepCo :: HasDebugCallStack => Coercion -> Coercion
    
    650 645
     mkRuntimeRepCo co
    
    651 646
       = assert (isTYPEorCONSTRAINT k1 && isTYPEorCONSTRAINT k2) $
    
    ... ... @@ -654,26 +649,6 @@ mkRuntimeRepCo co
    654 649
         kind_co = mkKindCo co  -- kind_co :: TYPE r1 ~ TYPE r2
    
    655 650
         Pair k1 k2 = coercionKind kind_co
    
    656 651
     
    
    657
    -{- Note [mkRuntimeRepCo]
    
    658
    -~~~~~~~~~~~~~~~~~~~~~~~~
    
    659
    -Given
    
    660
    -   class C a where { op :: Maybe a }
    
    661
    -we will get an axiom
    
    662
    -   axC a :: (C a :: CONSTRAINT r1) ~ (Maybe a :: TYPE r2)
    
    663
    -(See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim.)
    
    664
    -
    
    665
    -Then we may call mkRuntimeRepCo on (axC ty), and that will return
    
    666
    -   mkSelCo (SelTyCon 0 Nominal) (Kind (axC ty)) :: r1 ~ r2
    
    667
    -
    
    668
    -So mkSelCo needs to be happy with decomposing a coercion of kind
    
    669
    -   CONSTRAINT r1 ~ TYPE r2
    
    670
    -
    
    671
    -Hence the use of `tyConIsTYPEorCONSTRAINT` in the assertion `good_call`
    
    672
    -in `mkSelCo`. See #23018 for a concrete example.  (In this context it's
    
    673
    -important that TYPE and CONSTRAINT have the same arity and kind, not
    
    674
    -merely that they are not-apart; otherwise SelCo would not make sense.)
    
    675
    --}
    
    676
    -
    
    677 652
     isReflCoVar_maybe :: Var -> Maybe Coercion
    
    678 653
     -- If cv :: t~t then isReflCoVar_maybe cv = Just (Refl t)
    
    679 654
     -- Works on all kinds of Vars, not just CoVars
    
    ... ... @@ -1305,8 +1280,7 @@ mkSelCo_maybe cs co
    1305 1280
            , Just (tc2, tys2) <- splitTyConApp_maybe ty2
    
    1306 1281
            , let { len1 = length tys1
    
    1307 1282
                  ; len2 = length tys2 }
    
    1308
    -       =  (tc1 == tc2 || (tyConIsTYPEorCONSTRAINT tc1 && tyConIsTYPEorCONSTRAINT tc2))
    
    1309
    -                      -- tyConIsTYPEorCONSTRAINT: see Note [mkRuntimeRepCo]
    
    1283
    +       =  tc1 == tc2
    
    1310 1284
            && len1 == len2
    
    1311 1285
            && n < len1
    
    1312 1286
            && r == tyConRole (coercionRole co) tc1 n
    

  • compiler/GHC/Core/Lint.hs
    ... ... @@ -2891,13 +2891,9 @@ lint_branch ax_tc (CoAxBranch { cab_tvs = tvs, cab_cvs = cvs
    2891 2891
              hang (text "Inhomogeneous axiom")
    
    2892 2892
                 2 (text "lhs:" <+> ppr lhs <+> dcolon <+> ppr lhs_kind $$
    
    2893 2893
                    text "rhs:" <+> ppr rhs <+> dcolon <+> ppr rhs_kind) }
    
    2894
    -         -- Type and Constraint are not Apart, so this test allows
    
    2895
    -         -- the newtype axiom for a single-method class.  Indeed the
    
    2896
    -         -- whole reason Type and Constraint are not Apart is to allow
    
    2897
    -         -- such axioms!
    
    2898 2894
     
    
    2899
    --- these checks do not apply to newtype axioms
    
    2900 2895
     lint_family_branch :: TyCon -> CoAxBranch -> LintM ()
    
    2896
    +-- These checks do not apply to newtype axioms
    
    2901 2897
     lint_family_branch fam_tc br@(CoAxBranch { cab_tvs     = tvs
    
    2902 2898
                                              , cab_eta_tvs = eta_tvs
    
    2903 2899
                                              , cab_cvs     = cvs
    

  • compiler/GHC/Core/RoughMap.hs
    ... ... @@ -36,7 +36,6 @@ import GHC.Core.Type
    36 36
     import GHC.Utils.Outputable
    
    37 37
     import GHC.Types.Name
    
    38 38
     import GHC.Types.Name.Env
    
    39
    -import GHC.Builtin.Types.Prim( cONSTRAINTTyConName, tYPETyConName )
    
    40 39
     
    
    41 40
     import Control.Monad (join)
    
    42 41
     import Data.Data (Data)
    
    ... ... @@ -347,16 +346,7 @@ typeToRoughMatchTc ty
    347 346
     
    
    348 347
     roughMatchTyConName :: TyCon -> Name
    
    349 348
     roughMatchTyConName tc
    
    350
    -  | tc_name == cONSTRAINTTyConName
    
    351
    -  = tYPETyConName  -- TYPE and CONSTRAINT are not apart, so they must use
    
    352
    -                   -- the same rough-map key. We arbitrarily use TYPE.
    
    353
    -                   -- See Note [Type and Constraint are not apart]
    
    354
    -                   -- wrinkle (W1) in GHC.Builtin.Types.Prim
    
    355
    -  | otherwise
    
    356
    -  = assertPpr (isGenerativeTyCon tc Nominal) (ppr tc) tc_name
    
    357
    -  where
    
    358
    -    tc_name = tyConName tc
    
    359
    -
    
    349
    +  = assertPpr (isGenerativeTyCon tc Nominal) (ppr tc) (tyConName tc)
    
    360 350
     
    
    361 351
     -- | Trie of @[RoughMatchTc]@
    
    362 352
     --
    

  • compiler/GHC/Core/Type.hs
    ... ... @@ -1421,8 +1421,6 @@ piResultTy ty arg = case piResultTy_maybe ty arg of
    1421 1421
                           Nothing  -> pprPanic "piResultTy" (ppr ty $$ ppr arg)
    
    1422 1422
     
    
    1423 1423
     piResultTy_maybe :: Type -> Type -> Maybe Type
    
    1424
    --- We don't need a 'tc' version, because
    
    1425
    --- this function behaves the same for Type and Constraint
    
    1426 1424
     piResultTy_maybe ty arg = case coreFullView ty of
    
    1427 1425
       FunTy { ft_res = res } -> Just res
    
    1428 1426
     
    

  • compiler/GHC/Core/Unify.hs
    ... ... @@ -27,7 +27,6 @@ import GHC.Prelude
    27 27
     import GHC.Types.Var
    
    28 28
     import GHC.Types.Var.Env
    
    29 29
     import GHC.Types.Var.Set
    
    30
    -import GHC.Builtin.Names( tYPETyConKey, cONSTRAINTTyConKey )
    
    31 30
     import GHC.Core.Type     hiding ( getTvSubstEnv )
    
    32 31
     import GHC.Core.Coercion hiding ( getCvSubstEnv )
    
    33 32
     import GHC.Core.Predicate( scopedSort )
    
    ... ... @@ -98,8 +97,6 @@ of ways. Here we summarise, but see Note [Specification of unification].
    98 97
              See Note [Apartness and type families]
    
    99 98
         * MARInfinite (occurs check):
    
    100 99
              See Note [Infinitary substitutions]
    
    101
    -    * MARTypeVsConstraint:
    
    102
    -         See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim
    
    103 100
         * MARCast (obscure):
    
    104 101
              See (KCU2) in Note [Kind coercions in Unify]
    
    105 102
     
    
    ... ... @@ -997,16 +994,12 @@ data UnifyResultM a = Unifiable a -- the subst that unifies the types
    997 994
     
    
    998 995
     -- | Why are two types 'MaybeApart'? 'MARInfinite' takes precedence:
    
    999 996
     -- This is used (only) in Note [Infinitary substitution in lookup] in GHC.Core.InstEnv
    
    1000
    --- As of Feb 2022, we never differentiate between MARTypeFamily and MARTypeVsConstraint;
    
    1001
    --- it's really only MARInfinite that's interesting here.
    
    997
    +-- It's really only MARInfinite that's interesting here.
    
    1002 998
     data MaybeApartReason
    
    1003 999
       = MARTypeFamily   -- ^ matching e.g. F Int ~? Bool
    
    1004 1000
     
    
    1005 1001
       | MARInfinite     -- ^ matching e.g. a ~? Maybe a
    
    1006 1002
     
    
    1007
    -  | MARTypeVsConstraint  -- ^ matching Type ~? Constraint or the arrow types
    
    1008
    -    -- See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim
    
    1009
    -
    
    1010 1003
       | MARCast         -- ^ Very obscure.
    
    1011 1004
         -- See (KCU2) in Note [Kind coercions in Unify]
    
    1012 1005
     
    
    ... ... @@ -1015,13 +1008,11 @@ combineMAR :: MaybeApartReason -> MaybeApartReason -> MaybeApartReason
    1015 1008
     -- See (UR1) in Note [Unification result] for why MARInfinite wins
    
    1016 1009
     combineMAR MARInfinite         _ = MARInfinite   -- MARInfinite wins
    
    1017 1010
     combineMAR MARTypeFamily       r = r             -- Otherwise it doesn't really matter
    
    1018
    -combineMAR MARTypeVsConstraint r = r
    
    1019 1011
     combineMAR MARCast             r = r
    
    1020 1012
     
    
    1021 1013
     instance Outputable MaybeApartReason where
    
    1022 1014
       ppr MARTypeFamily       = text "MARTypeFamily"
    
    1023 1015
       ppr MARInfinite         = text "MARInfinite"
    
    1024
    -  ppr MARTypeVsConstraint = text "MARTypeVsConstraint"
    
    1025 1016
       ppr MARCast             = text "MARCast"
    
    1026 1017
     
    
    1027 1018
     instance Semigroup MaybeApartReason where
    
    ... ... @@ -1729,30 +1720,6 @@ unify_ty env ty1 ty2 kco
    1729 1720
            ; unify_tc_app env tc1 tys1 tys2
    
    1730 1721
            }
    
    1731 1722
     
    
    1732
    -  -- TYPE and CONSTRAINT are not Apart
    
    1733
    -  -- See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim
    
    1734
    -  -- NB: at this point we know that the two TyCons do not match
    
    1735
    -  | Just (tc1,_) <- mb_tc_app1, let u1 = tyConUnique tc1
    
    1736
    -  , Just (tc2,_) <- mb_tc_app2, let u2 = tyConUnique tc2
    
    1737
    -  , (u1 == tYPETyConKey && u2 == cONSTRAINTTyConKey) ||
    
    1738
    -    (u2 == tYPETyConKey && u1 == cONSTRAINTTyConKey)
    
    1739
    -  = maybeApart MARTypeVsConstraint
    
    1740
    -    -- We don't bother to look inside; wrinkle (W3) in GHC.Builtin.Types.Prim
    
    1741
    -    -- Note [Type and Constraint are not apart]
    
    1742
    -
    
    1743
    -  -- The arrow types are not Apart
    
    1744
    -  -- See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim
    
    1745
    -  --     wrinkle (W2)
    
    1746
    -  -- NB1: at this point we know that the two TyCons do not match
    
    1747
    -  -- NB2: In the common FunTy/FunTy case you might wonder if we want to go via
    
    1748
    -  --      splitTyConApp_maybe.  But yes we do: we need to look at those implied
    
    1749
    -  --      kind argument in order to satisfy (Unification Kind Invariant)
    
    1750
    -  | FunTy {} <- ty1
    
    1751
    -  , FunTy {} <- ty2
    
    1752
    -  = maybeApart MARTypeVsConstraint
    
    1753
    -    -- We don't bother to look inside; wrinkle (W3) in GHC.Builtin.Types.Prim
    
    1754
    -    -- Note [Type and Constraint are not apart]
    
    1755
    -
    
    1756 1723
       where
    
    1757 1724
         mb_tc_app1 = splitTyConApp_maybe ty1
    
    1758 1725
         mb_tc_app2 = splitTyConApp_maybe ty2
    

  • compiler/GHC/Driver/MakeFile.hs
    ... ... @@ -55,6 +55,7 @@ import Data.IORef
    55 55
     import qualified Data.Set as Set
    
    56 56
     import GHC.Iface.Errors.Types
    
    57 57
     import Data.Either
    
    58
    +import GHC.Data.Bag (listToBag)
    
    58 59
     
    
    59 60
     -----------------------------------------------------------------
    
    60 61
     --
    
    ... ... @@ -237,19 +238,6 @@ processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode _ (ModuleN
    237 238
                   obj_file  = msObjFilePath node
    
    238 239
                   obj_files = insertSuffixes obj_file extra_suffixes
    
    239 240
     
    
    240
    -              do_imp loc is_boot pkg_qual imp_mod
    
    241
    -                = do { mb_hi <- findDependency hsc_env loc pkg_qual imp_mod
    
    242
    -                                               is_boot include_pkg_deps
    
    243
    -                     ; case mb_hi of {
    
    244
    -                           Nothing      -> return () ;
    
    245
    -                           Just hi_file -> do
    
    246
    -                     { let hi_files = insertSuffixes hi_file extra_suffixes
    
    247
    -                           write_dep (obj,hi) = writeDependency root hdl [obj] hi
    
    248
    -
    
    249
    -                        -- Add one dependency for each suffix;
    
    250
    -                        -- e.g.         A.o   : B.hi
    
    251
    -                        --              A.x_o : B.x_hi
    
    252
    -                     ; mapM_ write_dep (obj_files `zip` hi_files) }}}
    
    253 241
     
    
    254 242
     
    
    255 243
                     -- Emit std dependency of the object(s) on the source file
    
    ... ... @@ -280,15 +268,33 @@ processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode _ (ModuleN
    280 268
     
    
    281 269
                     -- Emit a dependency for each import
    
    282 270
     
    
    283
    -        ; let do_imps is_boot idecls = sequence_
    
    284
    -                    [ do_imp loc is_boot mb_pkg mod
    
    271
    +        ; let find_dep loc is_boot pkg_qual imp_mod = findDependency hsc_env loc pkg_qual imp_mod is_boot include_pkg_deps
    
    272
    +
    
    273
    +              find_deps is_boot idecls = sequence
    
    274
    +                    [ find_dep loc is_boot mb_pkg mod
    
    285 275
                         | (_lvl, mb_pkg, L loc mod) <- idecls,
    
    286 276
                           mod `notElem` excl_mods ]
    
    287 277
     
    
    288
    -        ; do_imps IsBoot (map ((,,) NormalLevel NoPkgQual) (ms_srcimps node))
    
    289
    -        ; do_imps NotBoot (ms_imps node)
    
    290
    -        }
    
    278
    +              do_imp hi_file = do
    
    279
    +                let hi_files = insertSuffixes hi_file extra_suffixes
    
    280
    +                    write_dep (obj,hi) = writeDependency root hdl [obj] hi
    
    281
    +
    
    282
    +                 -- Add one dependency for each suffix;
    
    283
    +                 -- e.g.         A.o   : B.hi
    
    284
    +                 --              A.x_o : B.x_hi
    
    285
    +                mapM_ write_dep (obj_files `zip` hi_files)
    
    291 286
     
    
    287
    +        ; (missing_boot_dep_errs, boot_deps) <- partitionEithers <$> find_deps IsBoot (map ((,,) NormalLevel NoPkgQual) (ms_srcimps node))
    
    288
    +        ; (missing_not_boot_dep_errs, not_boot_deps) <- partitionEithers <$> find_deps NotBoot (ms_imps node)
    
    289
    +
    
    290
    +        ; let all_missing_errors = missing_boot_dep_errs ++ missing_not_boot_dep_errs
    
    291
    +
    
    292
    +        ; if null all_missing_errors
    
    293
    +            then mapM_ (mapM_ do_imp) (boot_deps ++ not_boot_deps)
    
    294
    +            else do
    
    295
    +              let sec = initSourceErrorContext (hsc_dflags hsc_env)
    
    296
    +              throwErrors sec (mkMessages (listToBag all_missing_errors))
    
    297
    +        }
    
    292 298
     
    
    293 299
     findDependency  :: HscEnv
    
    294 300
                     -> SrcSpan
    
    ... ... @@ -296,7 +302,7 @@ findDependency :: HscEnv
    296 302
                     -> ModuleName           -- Imported module
    
    297 303
                     -> IsBootInterface      -- Source import
    
    298 304
                     -> Bool                 -- Record dependency on package modules
    
    299
    -                -> IO (Maybe FilePath)  -- Interface file
    
    305
    +                -> IO (Either (MsgEnvelope GhcMessage) (Maybe FilePath))  -- Interface file
    
    300 306
     findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps = do
    
    301 307
       -- Find the module; this will be fast because
    
    302 308
       -- we've done it once during downsweep
    
    ... ... @@ -305,16 +311,15 @@ findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps = do
    305 311
         Found loc _
    
    306 312
             -- Home package: just depend on the .hi or hi-boot file
    
    307 313
             | isJust (ml_hs_file loc) || include_pkg_deps
    
    308
    -        -> return (Just (ml_hi_file loc))
    
    314
    +        -> return (Right (Just (ml_hi_file loc)))
    
    309 315
     
    
    310 316
             -- Not in this package: we don't need a dependency
    
    311 317
             | otherwise
    
    312
    -        -> return Nothing
    
    318
    +        -> return (Right Nothing)
    
    313 319
     
    
    314 320
         fail ->
    
    315
    -      let sec = initSourceErrorContext (hsc_dflags hsc_env)
    
    316
    -      in
    
    317
    -        throwOneError sec $
    
    321
    +      return $
    
    322
    +        Left $
    
    318 323
               mkPlainErrorMsgEnvelope srcloc $
    
    319 324
               GhcDriverMessage $ DriverInterfaceError $
    
    320 325
                  (Can'tFindInterface (cannotFindModule hsc_env imp fail) (LookingForModule imp is_boot))
    

  • compiler/GHC/StgToJS/Apply.hs
    ... ... @@ -185,7 +185,7 @@ genApp ctx i args
    185 185
           as'      <- concatMapM genArg args
    
    186 186
           ei       <- varForEntryId i
    
    187 187
           let ra = mconcat . reverse $
    
    188
    -                 zipWith (\r a -> toJExpr r |= a) [R1 ..] as'
    
    188
    +                 zipWith (\r a -> toJExpr r |= a) regsFromR1 as'
    
    189 189
           p <- pushLneFrame n ctx
    
    190 190
           a <- adjSp 1 -- for the header (which will only be written when the thread is suspended)
    
    191 191
           return (ra <> p <> a <> returnS ei, ExprCont)
    
    ... ... @@ -464,42 +464,31 @@ specTag spec = Bits.shiftL (specVars spec) 8 Bits..|. specArgs spec
    464 464
     specTagExpr :: ApplySpec -> JStgExpr
    
    465 465
     specTagExpr = toJExpr . specTag
    
    466 466
     
    
    467
    --- | Build arrays to quickly lookup apply functions
    
    467
    +-- | Build functions to quickly lookup apply functions
    
    468 468
     --
    
    469
    ---  h$apply[r << 8 | n] = function application for r regs, n args
    
    470
    ---  h$paps[r]           = partial application for r registers (number of args is in the object)
    
    469
    +--  h$apply(r << 8 | n) = function application for r regs, n args
    
    470
    +--  h$paps(r)           = partial application for r registers (number of args is in the object)
    
    471 471
     mkApplyArr :: JSM JStgStat
    
    472 472
     mkApplyArr =
    
    473
    -  do mk_ap_gens  <- jFor (|= zero_) (.<. Int 65536) preIncrS
    
    474
    -                    \j -> hdApply .! j |= hdApGen
    
    475
    -     mk_pap_gens <- jFor (|= zero_) (.<. Int 128) preIncrS
    
    476
    -                    \j -> hdPaps .! j |=  hdPapGen
    
    473
    +  do paps_fun <- jFunction (name hdPapsStr) \(MkSolo i) -> pure $ SwitchStat i (map case_pap specPap) (returnS hdPapGen)
    
    474
    +     apply_fun <- jFunction (name hdApplyStr) \(MkSolo i) -> pure $ SwitchStat i (mapMaybe' case_apply applySpec) (returnS hdApGen)
    
    477 475
          return $ mconcat
    
    478
    -       [ name hdApplyStr ||= toJExpr (JList [])
    
    479
    -       , name hdPapsStr  ||= toJExpr (JList [])
    
    480
    -       , ApplStat (hdInitStatic .^ "push")
    
    481
    -         [ jLam' $
    
    482
    -           mconcat
    
    483
    -           [ mk_ap_gens
    
    484
    -           , mk_pap_gens
    
    485
    -           , mconcat (map assignSpec applySpec)
    
    486
    -           , mconcat (map assignPap specPap)
    
    487
    -           ]
    
    488
    -         ]
    
    476
    +       [ paps_fun
    
    477
    +       , apply_fun
    
    489 478
            ]
    
    490 479
       where
    
    491
    -    assignSpec :: ApplySpec -> JStgStat
    
    492
    -    assignSpec spec = case specConv spec of
    
    480
    +    case_apply :: ApplySpec -> Maybe (JStgExpr,JStgStat)
    
    481
    +    case_apply spec = case specConv spec of
    
    493 482
           -- both fast/slow (regs/stack) specialized apply functions have the same
    
    494 483
           -- tags. We store the stack ones in the array because they are used as
    
    495 484
           -- continuation stack frames.
    
    496
    -      StackConv -> hdApply .! specTagExpr spec |= specApplyExpr spec
    
    497
    -      RegsConv  -> mempty
    
    485
    +      StackConv -> Just (specTagExpr spec, returnS (specApplyExpr spec))
    
    486
    +      RegsConv  -> Nothing
    
    498 487
     
    
    499 488
         hdPap_ = unpackFS hdPapStr_
    
    500 489
     
    
    501
    -    assignPap :: Int -> JStgStat
    
    502
    -    assignPap p = hdPaps .! toJExpr p |= global (mkFastString (hdPap_ ++ show p))
    
    490
    +    case_pap :: Int -> (JStgExpr, JStgStat)
    
    491
    +    case_pap p = (toJExpr p,  returnS $ global (mkFastString (hdPap_ ++ show p)))
    
    503 492
     
    
    504 493
     -- | Push a continuation on the stack
    
    505 494
     --
    
    ... ... @@ -619,7 +608,7 @@ genericStackApply cfg = closure info body
    619 608
                              -- compute new tag with consumed register values and args removed
    
    620 609
                              , newTag |= ((given_regs-needed_regs).<<.8) .|. (given_args - needed_args)
    
    621 610
                              -- find application function for the remaining regs/args
    
    622
    -                         , newAp |= hdApply .! newTag
    
    611
    +                         , newAp |= ApplExpr hdApply [newTag]
    
    623 612
                              , traceRts cfg (jString "h$ap_gen: next: " + (newAp .^ "n"))
    
    624 613
     
    
    625 614
                              -- Drop used registers from the stack.
    
    ... ... @@ -643,7 +632,7 @@ genericStackApply cfg = closure info body
    643 632
                              -----------------------------
    
    644 633
                              [ traceRts cfg (jString "h$ap_gen: undersat")
    
    645 634
                              -- find PAP entry function corresponding to given_regs count
    
    646
    -                         , p      |= hdPaps .! given_regs
    
    635
    +                         , p      |= ApplExpr hdPaps [given_regs]
    
    647 636
     
    
    648 637
                              -- build PAP payload: R1 + tag + given register values
    
    649 638
                              , newTag |= ((needed_regs-given_regs) .<<. 8) .|. (needed_args-given_args)
    
    ... ... @@ -716,7 +705,7 @@ genericFastApply s =
    716 705
                  do push_all_regs <- pushAllRegs tag
    
    717 706
                     return $ mconcat $
    
    718 707
                       [ push_all_regs
    
    719
    -                  , ap |= hdApply .! tag
    
    708
    +                  , ap |= ApplExpr hdApply [tag]
    
    720 709
                       , ifS (ap .===. hdApGen)
    
    721 710
                         ((sp |= sp + 2) <> (stack .! (sp-1) |= tag))
    
    722 711
                         (sp |= sp + 1)
    
    ... ... @@ -750,7 +739,7 @@ genericFastApply s =
    750 739
                     , traceRts s (jString "h$ap_gen_fast: oversat " + sp)
    
    751 740
                     , push_args
    
    752 741
                     , newTag |= ((myRegs-( arity.>>.8)).<<.8).|.myAr-ar
    
    753
    -                , newAp |= hdApply .! newTag
    
    742
    +                , newAp |= ApplExpr hdApply [newTag]
    
    754 743
                     , ifS (newAp .===. hdApGen)
    
    755 744
                       ((sp |= sp + 2) <> (stack .! (sp - 1) |= newTag))
    
    756 745
                       (sp |= sp + 1)
    
    ... ... @@ -761,7 +750,7 @@ genericFastApply s =
    761 750
                    -- else
    
    762 751
                     [traceRts s (jString "h$ap_gen_fast: undersat: " + myRegs + jString " " + tag)
    
    763 752
                     , jwhenS (tag .!=. 0) $ mconcat
    
    764
    -                  [ p |= hdPaps .! myRegs
    
    753
    +                  [ p |= ApplExpr hdPaps [myRegs]
    
    765 754
                       , dat |= toJExpr [r1, ((arity .>>. 8)-myRegs)*256+ar-myAr]
    
    766 755
                       , get_regs
    
    767 756
                       , r1 |= initClosure s p dat jCurrentCCS
    
    ... ... @@ -773,14 +762,24 @@ genericFastApply s =
    773 762
         pushAllRegs :: JStgExpr -> JSM JStgStat
    
    774 763
         pushAllRegs tag =
    
    775 764
           jVar \regs ->
    
    776
    -             return $ mconcat $
    
    777
    -             [ regs |= tag .>>. 8
    
    778
    -             , sp |= sp + regs
    
    779
    -             , SwitchStat regs (map pushReg [65,64..2]) mempty
    
    780
    -             ]
    
    781
    -      where
    
    782
    -        pushReg :: Int -> (JStgExpr, JStgStat)
    
    783
    -        pushReg r = (toJExpr (r-1),  stack .! (sp - toJExpr (r - 2)) |= jsReg r)
    
    765
    +             let max_low_reg = regNumber maxLowReg
    
    766
    +                 low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    767
    +                 pushReg :: Int -> (JStgExpr, JStgStat)
    
    768
    +                 pushReg r = (toJExpr r,  stack .! (sp - toJExpr (r - 2)) |= jsReg r)
    
    769
    +             in return $ mconcat $
    
    770
    +                  [ regs |= tag .>>. 8
    
    771
    +                  , sp |= sp + regs
    
    772
    +                    -- increment the number of regs by 1, so that it matches register
    
    773
    +                    -- numbers (R1 is not used for args)
    
    774
    +                  , postIncrS regs
    
    775
    +                    -- copy high registers with a loop
    
    776
    +                  , WhileStat False (regs .>. toJExpr max_low_reg) $ mconcat
    
    777
    +                      -- rN stored in stack[sp - N - 2] so that r2 is stored in stack[sp], etc.
    
    778
    +                      [ stack .! (sp - regs - 2) |= highReg_expr regs
    
    779
    +                      , postDecrS regs
    
    780
    +                      ]
    
    781
    +                  , SwitchStat regs (map pushReg low_regs) mempty
    
    782
    +                  ]
    
    784 783
     
    
    785 784
         pushArgs :: JStgExpr -> JStgExpr -> JSM JStgStat
    
    786 785
         pushArgs start end =
    
    ... ... @@ -906,7 +905,7 @@ stackApply s fun_name nargs nvars =
    906 905
                  [ rs |= (arity .>>. 8)
    
    907 906
                  , loadRegs rs
    
    908 907
                  , sp |= sp - rs
    
    909
    -             , newAp |= (hdApply .! ((toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)))
    
    908
    +             , newAp |= ApplExpr hdApply [(toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)]
    
    910 909
                  , stack .! sp |= newAp
    
    911 910
                  , profStat s pushRestoreCCS
    
    912 911
                  , traceRts s (toJExpr (fun_name <> ": new stack frame: ") + (newAp .^ "n"))
    
    ... ... @@ -989,7 +988,7 @@ fastApply s fun_name nargs nvars = if nargs == 0 && nvars == 0
    989 988
                                   + rsRemain)
    
    990 989
                     , saveRegs rs
    
    991 990
                     , sp |= sp + rsRemain + 1
    
    992
    -                , stack .! sp |= hdApply .! ((rsRemain.<<.8).|. (toJExpr nargs - mask8 arity))
    
    991
    +                , stack .! sp |= ApplExpr hdApply [(rsRemain.<<.8).|. (toJExpr nargs - mask8 arity)]
    
    993 992
                     , profStat s pushRestoreCCS
    
    994 993
                     , returnS c
    
    995 994
                     ]
    
    ... ... @@ -1238,14 +1237,30 @@ pap s r = closure (ClosureInfo
    1238 1237
                  , profStat s (enterCostCentreFun currentCCS)
    
    1239 1238
                  , extra |= (funOrPapArity c (Just f) .>>. 8) - toJExpr r
    
    1240 1239
                  , traceRts s (toJExpr (funcName <> ": pap extra args moving: ") + extra)
    
    1241
    -             , moveBy extra
    
    1240
    +             , case r of
    
    1241
    +                0 -> mempty -- in pap_0 we don't shift any register
    
    1242
    +                _ -> moveBy extra
    
    1242 1243
                  , loadOwnArgs d
    
    1243 1244
                  , r1 |= c
    
    1244 1245
                  , returnS f
    
    1245 1246
                  ]
    
    1246
    -    moveBy extra = SwitchStat extra
    
    1247
    -                   (reverse $ map moveCase [1..maxReg-r-1]) mempty
    
    1248
    -    moveCase m = (toJExpr m, jsReg (m+r+1) |= jsReg (m+1))
    
    1247
    +    moveBy extra =
    
    1248
    +      let max_low_reg = regNumber maxLowReg
    
    1249
    +          low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    1250
    +          move_case m = (toJExpr m, jsReg (m+r) |= jsReg m)
    
    1251
    +      in mconcat
    
    1252
    +          [ -- increment the number of args by 1, so that it matches register
    
    1253
    +            -- numbers (R1 is not used for args)
    
    1254
    +            postIncrS extra
    
    1255
    +            -- copy high registers with a loop
    
    1256
    +          ,  WhileStat False (extra .>. toJExpr max_low_reg) $ mconcat
    
    1257
    +              [ highReg_expr (extra + toJExpr r) |= highReg_expr extra
    
    1258
    +              , postDecrS extra
    
    1259
    +              ]
    
    1260
    +            -- then copy low registers with a case
    
    1261
    +          , SwitchStat extra (map move_case low_regs) mempty
    
    1262
    +          ]
    
    1263
    +
    
    1249 1264
         loadOwnArgs d = mconcat $ map (\r ->
    
    1250 1265
             jsReg (r+1) |= dField d (r+2)) [1..r]
    
    1251 1266
         dField d n = SelExpr d (name . mkFastString $ ('d':show (n-1)))
    
    ... ... @@ -1274,7 +1289,9 @@ papGen cfg =
    1274 1289
                     (jString "h$pap_gen: expected function or pap")
    
    1275 1290
                   , profStat cfg (enterCostCentreFun currentCCS)
    
    1276 1291
                   , traceRts cfg (jString "h$pap_gen: generic pap extra args moving: " + or)
    
    1292
    +                -- shift newly applied arguments into appropriate registers
    
    1277 1293
                   , appS hdMoveRegs2 [or, r]
    
    1294
    +                -- load stored arguments into lowest argument registers (i.e. starting from R2)
    
    1278 1295
                   , loadOwnArgs d r
    
    1279 1296
                   , r1 |= c
    
    1280 1297
                   , returnS f
    
    ... ... @@ -1285,9 +1302,22 @@ papGen cfg =
    1285 1302
         funcIdent = name funcName
    
    1286 1303
         funcName = hdPapGenStr
    
    1287 1304
         loadOwnArgs d r =
    
    1288
    -      let prop n = d .^ ("d" <> mkFastString (show $ n+1))
    
    1289
    -          loadOwnArg n = (toJExpr n, jsReg (n+1) |= prop n)
    
    1290
    -      in  SwitchStat r (map loadOwnArg [127,126..1]) mempty
    
    1305
    +      let prop n = d .^ (mkFastString ("d" ++ show n))
    
    1306
    +          loadOwnArg n = (toJExpr n, jsReg n |= prop n)
    
    1307
    +          max_low_reg = regNumber maxLowReg
    
    1308
    +          low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    1309
    +      in  mconcat
    
    1310
    +            [ -- increment the number of args by 1, so that it matches register
    
    1311
    +              -- numbers (R1 is not used for args) and PAP fields (starting from d2)
    
    1312
    +              postIncrS r
    
    1313
    +              -- copy high registers with a loop
    
    1314
    +            ,  WhileStat False (r .>. toJExpr max_low_reg) $ mconcat
    
    1315
    +                [ highReg_expr r |= (d .! (jString (fsLit "d") + r))
    
    1316
    +                , postDecrS r
    
    1317
    +                ]
    
    1318
    +              -- then copy low registers with a case.
    
    1319
    +            , SwitchStat r (map loadOwnArg low_regs) mempty
    
    1320
    +            ]
    
    1291 1321
     
    
    1292 1322
     -- general utilities
    
    1293 1323
     -- move the first n registers, starting at R2, m places up (do not use with negative m)
    
    ... ... @@ -1301,7 +1331,7 @@ moveRegs2 = jFunction (name hdMoveRegs2) moveSwitch
    1301 1331
         switchCase n m = (toJExpr $
    
    1302 1332
                           (n `Bits.shiftL` 8) Bits..|. m
    
    1303 1333
                          , mconcat (map (`moveRegFast` m) [n+1,n..2])
    
    1304
    -                       <> BreakStat Nothing {-[j| break; |]-})
    
    1334
    +                       <> BreakStat Nothing)
    
    1305 1335
         moveRegFast n m = jsReg (n+m) |= jsReg n
    
    1306 1336
         -- fallback
    
    1307 1337
         defaultCase n m =
    

  • compiler/GHC/StgToJS/Expr.hs
    ... ... @@ -312,7 +312,7 @@ genBody ctx startReg args e typ = do
    312 312
       -- load arguments into local variables
    
    313 313
       la <- do
    
    314 314
         args' <- concatMapM genIdArgI args
    
    315
    -    return (declAssignAll args' (fmap toJExpr [startReg..]))
    
    315
    +    return (declAssignAll args' (jsRegsFrom startReg))
    
    316 316
     
    
    317 317
       -- assert that arguments have valid runtime reps
    
    318 318
       lav <- verifyRuntimeReps args
    
    ... ... @@ -665,7 +665,7 @@ genCase ctx bnd e at alts l
    665 665
       | otherwise = do
    
    666 666
           rj       <- genRet ctx bnd at alts l
    
    667 667
           let ctx' = ctxSetTop bnd
    
    668
    -                  $ ctxSetTarget (assocIdExprs bnd (map toJExpr [R1 ..]))
    
    668
    +                  $ ctxSetTarget (assocIdExprs bnd jsRegsFromR1)
    
    669 669
                       $ ctx
    
    670 670
           (ej, _r) <- genExpr ctx' e
    
    671 671
           return (rj <> ej, ExprCont)
    
    ... ... @@ -730,7 +730,7 @@ genRet ctx e at as l = freshIdent >>= f
    730 730
     
    
    731 731
         fun free = resetSlots $ do
    
    732 732
           decs          <- declVarsForId e
    
    733
    -      load          <- flip assignAll (map toJExpr [R1 ..]) . map toJExpr <$> identsForId e
    
    733
    +      load          <- flip assignAll jsRegsFromR1 . map toJExpr <$> identsForId e
    
    734 734
           loadv         <- verifyRuntimeReps [e]
    
    735 735
           ras           <- loadRetArgs free
    
    736 736
           rasv          <- verifyRuntimeReps (map (\(x,_,_)->x) free)
    

  • compiler/GHC/StgToJS/Regs.hs
    1 1
     {-# LANGUAGE OverloadedStrings #-}
    
    2
    +{-# LANGUAGE PatternSynonyms #-}
    
    2 3
     
    
    3 4
     module GHC.StgToJS.Regs
    
    4 5
       ( StgReg (..)
    
    ... ... @@ -6,17 +7,25 @@ module GHC.StgToJS.Regs
    6 7
       , sp
    
    7 8
       , stack
    
    8 9
       , r1, r2, r3, r4
    
    10
    +  , pattern R1, pattern R2, pattern R3, pattern R4
    
    9 11
       , regsFromR1
    
    10 12
       , regsFromR2
    
    13
    +  , regsFromTo
    
    14
    +  , jsRegsFrom
    
    11 15
       , jsRegsFromR1
    
    12 16
       , jsRegsFromR2
    
    13 17
       , StgRet (..)
    
    14
    -  , jsRegToInt
    
    15
    -  , intToJSReg
    
    18
    +  , regNumber
    
    16 19
       , jsReg
    
    20
    +  , highReg
    
    21
    +  , highReg_expr
    
    17 22
       , maxReg
    
    23
    +  , maxLowReg
    
    18 24
       , minReg
    
    25
    +  , minHighReg
    
    19 26
       , lowRegs
    
    27
    +  , lowRegsCount
    
    28
    +  , lowRegsIdents
    
    20 29
       , retRegs
    
    21 30
       , register
    
    22 31
       , foreignRegister
    
    ... ... @@ -32,6 +41,7 @@ import GHC.JS.Make
    32 41
     import GHC.StgToJS.Symbols
    
    33 42
     
    
    34 43
     import GHC.Data.FastString
    
    44
    +import GHC.Utils.Panic.Plain
    
    35 45
     
    
    36 46
     import Data.Array
    
    37 47
     import qualified Data.ByteString.Char8 as BSC
    
    ... ... @@ -39,26 +49,15 @@ import Data.Char
    39 49
     import Data.Semigroup ((<>))
    
    40 50
     
    
    41 51
     -- | General purpose "registers"
    
    42
    ---
    
    43
    --- The JS backend arbitrarily supports 128 registers
    
    44
    -data StgReg
    
    45
    -  = R1  | R2  | R3  | R4  | R5  | R6  | R7  | R8
    
    46
    -  | R9  | R10 | R11 | R12 | R13 | R14 | R15 | R16
    
    47
    -  | R17 | R18 | R19 | R20 | R21 | R22 | R23 | R24
    
    48
    -  | R25 | R26 | R27 | R28 | R29 | R30 | R31 | R32
    
    49
    -  | R33 | R34 | R35 | R36 | R37 | R38 | R39 | R40
    
    50
    -  | R41 | R42 | R43 | R44 | R45 | R46 | R47 | R48
    
    51
    -  | R49 | R50 | R51 | R52 | R53 | R54 | R55 | R56
    
    52
    -  | R57 | R58 | R59 | R60 | R61 | R62 | R63 | R64
    
    53
    -  | R65 | R66 | R67 | R68 | R69 | R70 | R71 | R72
    
    54
    -  | R73 | R74 | R75 | R76 | R77 | R78 | R79 | R80
    
    55
    -  | R81 | R82 | R83 | R84 | R85 | R86 | R87 | R88
    
    56
    -  | R89 | R90 | R91 | R92 | R93 | R94 | R95 | R96
    
    57
    -  | R97  | R98  | R99  | R100 | R101 | R102 | R103 | R104
    
    58
    -  | R105 | R106 | R107 | R108 | R109 | R110 | R111 | R112
    
    59
    -  | R113 | R114 | R115 | R116 | R117 | R118 | R119 | R120
    
    60
    -  | R121 | R122 | R123 | R124 | R125 | R126 | R127 | R128
    
    61
    -  deriving (Eq, Ord, Show, Enum, Bounded, Ix)
    
    52
    +newtype StgReg
    
    53
    +  = StgReg Int
    
    54
    +  deriving (Eq,Ord,Ix)
    
    55
    +
    
    56
    +pattern R1, R2, R3, R4 :: StgReg
    
    57
    +pattern R1 = StgReg 0
    
    58
    +pattern R2 = StgReg 1
    
    59
    +pattern R3 = StgReg 2
    
    60
    +pattern R4 = StgReg 3
    
    62 61
     
    
    63 62
     -- | Stack registers
    
    64 63
     data Special
    
    ... ... @@ -78,7 +77,7 @@ instance ToJExpr Special where
    78 77
       toJExpr Sp     = hdStackPtr
    
    79 78
     
    
    80 79
     instance ToJExpr StgReg where
    
    81
    -  toJExpr r = registers ! r
    
    80
    +  toJExpr r = register r
    
    82 81
     
    
    83 82
     instance ToJExpr StgRet where
    
    84 83
       toJExpr r = rets ! r
    
    ... ... @@ -99,25 +98,42 @@ r2 = toJExpr R2
    99 98
     r3 = toJExpr R3
    
    100 99
     r4 = toJExpr R4
    
    101 100
     
    
    101
    +-- | 1-indexed register number (R1 has index 1)
    
    102
    +regNumber :: StgReg -> Int
    
    103
    +regNumber (StgReg r) = r+1
    
    102 104
     
    
    103
    -jsRegToInt :: StgReg -> Int
    
    104
    -jsRegToInt = (+1) . fromEnum
    
    105
    +-- | StgReg from 1-indexed number
    
    106
    +regFromNumber :: Int -> StgReg
    
    107
    +regFromNumber r = assert (r >= 1) $ StgReg (r-1)
    
    105 108
     
    
    106
    -intToJSReg :: Int -> StgReg
    
    107
    -intToJSReg r = toEnum (r - 1)
    
    109
    +regsFromTo :: StgReg -> StgReg -> [StgReg]
    
    110
    +regsFromTo (StgReg x) (StgReg y) = map StgReg [x .. y]
    
    108 111
     
    
    112
    +-- | Register expression from its 1-indexed index
    
    109 113
     jsReg :: Int -> JStgExpr
    
    110
    -jsReg r = toJExpr (intToJSReg r)
    
    114
    +jsReg r = toJExpr (regFromNumber r)
    
    115
    +
    
    116
    +minReg :: StgReg
    
    117
    +minReg = R1
    
    111 118
     
    
    112
    -maxReg :: Int
    
    113
    -maxReg = jsRegToInt maxBound
    
    119
    +maxReg :: StgReg
    
    120
    +maxReg = regFromNumber maxBound
    
    114 121
     
    
    115
    -minReg :: Int
    
    116
    -minReg = jsRegToInt minBound
    
    122
    +lowRegsCount :: Int
    
    123
    +lowRegsCount = 31
    
    124
    +
    
    125
    +maxLowReg :: StgReg
    
    126
    +maxLowReg = regFromNumber lowRegsCount
    
    127
    +
    
    128
    +-- | First register stored in h$regs array instead of having its own top-level
    
    129
    +-- variable
    
    130
    +minHighReg :: StgReg
    
    131
    +minHighReg = case maxLowReg of
    
    132
    +  StgReg r -> StgReg (r+1)
    
    117 133
     
    
    118 134
     -- | List of registers, starting from R1
    
    119 135
     regsFromR1 :: [StgReg]
    
    120
    -regsFromR1 = enumFrom R1
    
    136
    +regsFromR1 = regsFromTo R1 maxReg ++ repeat (panic "StgToJS: code requires too many registers")
    
    121 137
     
    
    122 138
     -- | List of registers, starting from R2
    
    123 139
     regsFromR2 :: [StgReg]
    
    ... ... @@ -131,35 +147,59 @@ jsRegsFromR1 = fmap toJExpr regsFromR1
    131 147
     jsRegsFromR2 :: [JStgExpr]
    
    132 148
     jsRegsFromR2 = tail jsRegsFromR1
    
    133 149
     
    
    150
    +-- | List of registers, starting from given reg as JExpr
    
    151
    +jsRegsFrom :: StgReg -> [JStgExpr]
    
    152
    +jsRegsFrom (StgReg n) = drop n jsRegsFromR1
    
    153
    +
    
    154
    +-- | High register
    
    155
    +highReg :: Int -> JStgExpr
    
    156
    +highReg r = assert (r >= regNumber minHighReg) $ IdxExpr hdRegs (toJExpr (r - regNumber minHighReg))
    
    157
    +
    
    158
    +-- | High register indexing with a JS expression
    
    159
    +highReg_expr :: JStgExpr -> JStgExpr
    
    160
    +highReg_expr r = IdxExpr hdRegs (r - toJExpr (regNumber minHighReg))
    
    161
    +
    
    162
    +
    
    134 163
     ---------------------------------------------------
    
    135 164
     -- caches
    
    136 165
     ---------------------------------------------------
    
    137 166
     
    
    138
    -lowRegs :: [Ident]
    
    139
    -lowRegs = map reg_to_ident [R1 .. R31]
    
    140
    -  where reg_to_ident = name . mkFastString . (unpackFS hdStr ++) . map toLower . show
    
    167
    +lowRegs :: [StgReg]
    
    168
    +lowRegs = regsFromTo minReg maxLowReg
    
    169
    +
    
    170
    +lowRegsIdents :: [Ident]
    
    171
    +lowRegsIdents = map reg_to_ident lowRegs
    
    172
    +  where
    
    173
    +    -- low regs are named h$r1, h$r2, etc.
    
    174
    +    reg_to_ident r = name (mkFastString (unpackFS hdStr ++ "r" ++ show (regNumber r)))
    
    141 175
     
    
    142 176
     retRegs :: [Ident]
    
    143 177
     retRegs = [name . mkFastStringByteString
    
    144 178
                $ hdB <> BSC.pack (map toLower $ show n) | n <- enumFrom Ret1]
    
    145 179
     
    
    146
    --- cache JExpr representing StgReg
    
    147
    -registers :: Array StgReg JStgExpr
    
    148
    -registers = listArray (minBound, maxBound) (map (global . identFS) lowRegs ++ map regN [R32 .. R128])
    
    149
    -  where
    
    150
    -    regN :: StgReg -> JStgExpr
    
    151
    -    regN r = IdxExpr hdRegs (toJExpr (fromEnum r - 32))
    
    152
    -
    
    153 180
     -- cache JExpr representing StgRet
    
    154 181
     rets :: Array StgRet JStgExpr
    
    155 182
     rets = listArray (minBound, maxBound) (map retN (enumFrom Ret1))
    
    156 183
       where
    
    157 184
         retN = global . mkFastString . (unpackFS hdStr ++) . map toLower . show
    
    158 185
     
    
    159
    --- | Given a register, return the JS syntax object representing that register
    
    160
    -register :: StgReg -> JStgExpr
    
    161
    -register i = registers ! i
    
    162
    -
    
    163 186
     -- | Given a register, return the JS syntax object representing that register
    
    164 187
     foreignRegister :: StgRet -> JStgExpr
    
    165 188
     foreignRegister i = rets ! i
    
    189
    +
    
    190
    +-- | Given a register, return the JS syntax object representing that register
    
    191
    +register :: StgReg -> JStgExpr
    
    192
    +register i
    
    193
    +  | i <= maxCachedReg = register_cache ! i -- Expressions of common registers are cached.
    
    194
    +  | otherwise         = make_high_reg i    -- Expression of higher registers are made on the fly
    
    195
    +
    
    196
    +maxCachedReg :: StgReg
    
    197
    +maxCachedReg = regFromNumber 128
    
    198
    +
    
    199
    +-- cache JExpr representing StgReg
    
    200
    +register_cache :: Array StgReg JStgExpr
    
    201
    +register_cache = listArray (minReg, maxCachedReg) (map (global . identFS) lowRegsIdents ++ map make_high_reg (regsFromTo minHighReg maxCachedReg))
    
    202
    +
    
    203
    +-- | Make h$regs[XXX] expression for the register
    
    204
    +make_high_reg :: StgReg -> JStgExpr
    
    205
    +make_high_reg r = highReg (regNumber r)

  • compiler/GHC/StgToJS/Rts/Rts.hs
    ... ... @@ -54,7 +54,12 @@ import qualified Data.Bits as Bits
    54 54
     -- | The garbageCollector resets registers and result variables.
    
    55 55
     garbageCollector :: JSM JStgStat
    
    56 56
     garbageCollector = jBlock
    
    57
    -    [ jFunction' hdResetRegisters  (return $ mconcat $ map resetRegister [minBound..maxBound])
    
    57
    +    [ jFunction' hdResetRegisters  $ return $ mconcat
    
    58
    +        [ -- reset low registers explicitly
    
    59
    +          mconcat (map resetRegister lowRegs)
    
    60
    +          -- reset the whole h$regs array with h$regs.fill(null)
    
    61
    +        , toStat $ ApplExpr (hdRegs .^ "fill") [null_]
    
    62
    +        ]
    
    58 63
         , jFunction' hdResetResultVars (return $ mconcat $ map resetResultVar [minBound..maxBound])
    
    59 64
         ]
    
    60 65
     
    
    ... ... @@ -249,7 +254,7 @@ declRegs = do
    249 254
         loaders         <- loadRegs
    
    250 255
         return $
    
    251 256
           mconcat [ hdRegsStr ||= toJExpr (JList [])
    
    252
    -              , mconcat (map declReg lowRegs)
    
    257
    +              , mconcat (map declReg lowRegsIdents)
    
    253 258
                   , getters_setters
    
    254 259
                   , loaders
    
    255 260
                   ]
    
    ... ... @@ -259,15 +264,15 @@ declRegs = do
    259 264
     -- | JS payload to define getters and setters on the registers.
    
    260 265
     regGettersSetters :: JSM JStgStat
    
    261 266
     regGettersSetters =
    
    262
    -  do setters <- jFunction (name hdGetRegStr) (\(MkSolo n) -> return $ SwitchStat n getRegCases mempty)
    
    263
    -     getters <- jFunction (name hdSetRegStr) (\(n,v)      -> return $ SwitchStat n (setRegCases v) mempty)
    
    267
    +  do getters <- jFunction (name hdGetRegStr) (\(MkSolo n) -> return $ SwitchStat n getRegCases (defaultGetRegCase n))
    
    268
    +     setters <- jFunction (name hdSetRegStr) (\(n,v)      -> return $ SwitchStat n (setRegCases v) (defaultSetRegCase n v))
    
    264 269
          return $ setters <> getters
    
    265 270
       where
    
    266
    -    getRegCases =
    
    267
    -      map (\r -> (toJExpr (jsRegToInt r) , returnS (toJExpr r))) regsFromR1
    
    268
    -    setRegCases :: JStgExpr -> [(JStgExpr,JStgStat)]
    
    269
    -    setRegCases v =
    
    270
    -      map (\r -> (toJExpr (jsRegToInt r), (toJExpr r |= toJExpr v) <> returnS undefined_)) regsFromR1
    
    271
    +    getRegCases         = map (\r -> (toJExpr (regNumber r) , returnS (toJExpr r))) lowRegs
    
    272
    +    defaultGetRegCase n = returnS (highReg_expr n)
    
    273
    +
    
    274
    +    setRegCases v         = map (\r -> (toJExpr (regNumber r), (toJExpr r |= v) <> BreakStat Nothing)) lowRegs
    
    275
    +    defaultSetRegCase n v = highReg_expr n |= v
    
    271 276
     
    
    272 277
     -- | JS payload that defines the functions to load each register
    
    273 278
     loadRegs :: JSM JStgStat
    

  • compiler/GHC/StgToJS/Rts/Types.hs
    ... ... @@ -69,12 +69,3 @@ stackFrameSize tgt f =
    69 69
                     (tgt |= mask8 tag + 1)       -- else set to mask'd tag + 1
    
    70 70
                   ]
    
    71 71
               ))
    72
    -
    
    73
    -  --------------------------------------------------------------------------------
    
    74
    --- Register utilities
    
    75
    ---------------------------------------------------------------------------------
    
    76
    -
    
    77
    --- | Perform the computation 'f', on the range of registers bounded by 'start'
    
    78
    --- and 'end'.
    
    79
    -withRegs :: StgReg -> StgReg -> (StgReg -> JStgStat) -> JStgStat
    
    80
    -withRegs start end f = mconcat $ fmap f [start..end]

  • compiler/GHC/Tc/Instance/Class.hs
    ... ... @@ -963,11 +963,6 @@ matchTypeable clas [k,t] -- clas = Typeable
    963 963
       | k `eqType` naturalTy      = doTyLit knownNatClassName         t
    
    964 964
       | k `eqType` typeSymbolKind = doTyLit knownSymbolClassName      t
    
    965 965
       | k `eqType` charTy         = doTyLit knownCharClassName        t
    
    966
    -
    
    967
    -  -- TyCon applied to its kind args
    
    968
    -  -- No special treatment of Type and Constraint; they get distinct TypeReps
    
    969
    -  -- see wrinkle (W4) of Note [Type and Constraint are not apart]
    
    970
    -  --     in GHC.Builtin.Types.Prim.
    
    971 966
       | Just (tc, ks) <- splitTyConApp_maybe t -- See Note [Typeable (T a b c)]
    
    972 967
       , onlyNamedBndrsApplied tc ks            = doTyConApp clas t tc ks
    
    973 968
     
    

  • docs/users_guide/9.16.1-notes.rst
    ... ... @@ -16,6 +16,17 @@ Language
    16 16
       result, you may need to enable :extension:`DataKinds` in code that did not
    
    17 17
       previously require it.
    
    18 18
     
    
    19
    +- ``Type`` and ``Constraint`` are now (at last) completely distinct types, just as much
    
    20
    +  as ``Int`` and ``Bool``.  For example, you can now
    
    21
    +  write::
    
    22
    +
    
    23
    +    type family F a
    
    24
    +
    
    25
    +    type instance F Type = Int
    
    26
    +    type instance F Constraint = Bool
    
    27
    +
    
    28
    +  which was previously rejected with "Conflicting family instance declarations".
    
    29
    +
    
    19 30
     Compiler
    
    20 31
     ~~~~~~~~
    
    21 32
     
    

  • testsuite/tests/codeGen/should_run/all.T
    ... ... @@ -256,4 +256,4 @@ test('T24893', normal, compile_and_run, ['-O'])
    256 256
     test('CCallConv', [req_c], compile_and_run, ['CCallConv_c.c'])
    
    257 257
     test('T25364', normal, compile_and_run, [''])
    
    258 258
     test('T26061', normal, compile_and_run, [''])
    
    259
    -test('T26537', js_broken(26558), compile_and_run, ['-O2 -fregs-graph'])
    259
    +test('T26537', normal, compile_and_run, ['-O2 -fregs-graph'])

  • testsuite/tests/driver/Makefile
    ... ... @@ -415,6 +415,10 @@ test200:
    415 415
     	"$(TEST_HC)" $(TEST_HC_OPTS) -M -dep-suffix "" -dep-makefile $(DEPFILE200) D200.hs B200/C.hs A200.hs
    
    416 416
     	test -f $(DEPFILE200)
    
    417 417
     
    
    418
    +# Test that we produce "could not find module" errors for _all_ missing imports.
    
    419
    +T26551:
    
    420
    +	"$(TEST_HC)" $(TEST_HC_OPTS) -M T26551.hs || true
    
    421
    +
    
    418 422
     # -----------------------------------------------------------------------------
    
    419 423
     
    
    420 424
     T2566::
    

  • testsuite/tests/driver/T26551.hs
    1
    +module Main where
    
    2
    +
    
    3
    +import Foo
    
    4
    +import Bar
    
    5
    +import Baz

  • testsuite/tests/driver/T26551.stderr
    1
    +T26551.hs:3:8: [GHC-87110]
    
    2
    +    Could not find module ‘Foo’.
    
    3
    +    Use -v to see a list of the files searched for.
    
    4
    +
    
    5
    +T26551.hs:4:8: [GHC-87110]
    
    6
    +    Could not find module ‘Bar’.
    
    7
    +    Use -v to see a list of the files searched for.
    
    8
    +
    
    9
    +T26551.hs:5:8: [GHC-87110]
    
    10
    +    Could not find module ‘Baz’.
    
    11
    +    Use -v to see a list of the files searched for.

  • testsuite/tests/driver/all.T
    ... ... @@ -332,3 +332,4 @@ test('t25150', [extra_files(["t25150"])], multimod_compile, ['Main.hs', '-v0 -wo
    332 332
     test('T25382', normal, makefile_test, [])
    
    333 333
     test('T26018', req_c, makefile_test, [])
    
    334 334
     test('T24120', normal, compile, ['-Wunused-packages -hide-all-packages -package base -package system-cxx-std-lib'])
    
    335
    +test('T26551', [extra_files(['T26551.hs'])], makefile_test, [])

  • testsuite/tests/indexed-types/should_fail/T21092.hs
    ... ... @@ -7,3 +7,5 @@ type family F a
    7 7
     
    
    8 8
     type instance F Type = Int
    
    9 9
     type instance F Constraint = Bool
    
    10
    +
    
    11
    +-- Nov 2025: Type and Constraint are now Apart (#24279)

  • testsuite/tests/indexed-types/should_fail/T21092.stderr deleted
    1
    -
    
    2
    -T21092.hs:8:15: error: [GHC-34447]
    
    3
    -    Conflicting family instance declarations:
    
    4
    -      F (*) = Int -- Defined at T21092.hs:8:15
    
    5
    -      F Constraint = Bool -- Defined at T21092.hs:9:15

  • testsuite/tests/indexed-types/should_fail/all.T
    ... ... @@ -107,7 +107,7 @@ test('T8368', normal, compile_fail, [''])
    107 107
     test('T8368a', normal, compile_fail, [''])
    
    108 108
     test('T8518', normal, compile_fail, [''])
    
    109 109
     test('T9036', normal, compile_fail, [''])
    
    110
    -test('T21092', normal, compile_fail, [''])
    
    110
    +test('T21092', normal, compile, [''])   # Now compiles fine
    
    111 111
     test('T9167', normal, compile_fail, [''])
    
    112 112
     test('T9171', normal, compile_fail, [''])
    
    113 113
     test('T9097', normal, compile_fail, [''])
    

  • testsuite/tests/typecheck/should_fail/T24279.hs
    ... ... @@ -13,7 +13,7 @@ type G :: Type -> RuntimeRep -> Type
    13 13
     type family G a where
    
    14 14
       G (a b) = a
    
    15 15
     
    
    16
    --- Should be rejected
    
    16
    +-- Now (Nov 2025) accepted
    
    17 17
     foo :: (F (G Constraint)) -> Bool
    
    18 18
     foo x = x
    
    19 19
     
    
    ... ... @@ -22,10 +22,10 @@ type family H a b where
    22 22
       H a a = Int
    
    23 23
       H a b = Bool
    
    24 24
     
    
    25
    --- Should be rejected
    
    26
    -bar1 :: H TYPE CONSTRAINT -> Int
    
    25
    +-- Now (Nov 2025) accepted
    
    26
    +bar1 :: H TYPE CONSTRAINT -> Bool
    
    27 27
     bar1 x = x
    
    28 28
     
    
    29
    --- Should be rejected
    
    30
    -bar2 :: H Type Constraint -> Int
    
    29
    +-- Now (Nov 2025) accepted
    
    30
    +bar2 :: H Type Constraint -> Bool
    
    31 31
     bar2 x = x

  • testsuite/tests/typecheck/should_fail/T24279.stderr deleted
    1
    -
    
    2
    -T24279.hs:18:9: error: [GHC-83865]
    
    3
    -    • Couldn't match type ‘F CONSTRAINT’ with ‘Bool’
    
    4
    -      Expected: Bool
    
    5
    -        Actual: F (G Constraint)
    
    6
    -    • In the expression: x
    
    7
    -      In an equation for ‘foo’: foo x = x
    
    8
    -
    
    9
    -T24279.hs:27:10: error: [GHC-83865]
    
    10
    -    • Couldn't match expected type ‘Int’
    
    11
    -                  with actual type ‘H TYPE CONSTRAINT’
    
    12
    -    • In the expression: x
    
    13
    -      In an equation for ‘bar1’: bar1 x = x
    
    14
    -
    
    15
    -T24279.hs:31:10: error: [GHC-83865]
    
    16
    -    • Couldn't match expected type ‘Int’
    
    17
    -                  with actual type ‘H (*) Constraint’
    
    18
    -    • In the expression: x
    
    19
    -      In an equation for ‘bar2’: bar2 x = x

  • testsuite/tests/typecheck/should_fail/all.T
    ... ... @@ -718,7 +718,7 @@ test('T24064', normal, compile_fail, [''])
    718 718
     test('T24090a', normal, compile_fail, [''])
    
    719 719
     test('T24090b', normal, compile, ['']) # scheduled to become an actual error in GHC 9.16
    
    720 720
     test('T24298', normal, compile_fail, [''])
    
    721
    -test('T24279', normal, compile_fail, [''])
    
    721
    +test('T24279', normal, compile, [''])  # Now accepted (Nov 2025)
    
    722 722
     test('T24318', normal, compile_fail, [''])
    
    723 723
     
    
    724 724
     # all the various do expansion fail messages