Zubin pushed to branch wip/9.12.3-backports at Glasgow Haskell Compiler / GHC

Commits:

24 changed files:

Changes:

  • .gitlab/rel_eng/fetch-gitlab-artifacts/fetch_gitlab.py
    ... ... @@ -134,6 +134,9 @@ def fetch_artifacts(release: str, pipeline_id: int,
    134 134
                         logging.info(f'extracted docs {f} to {dest}')
    
    135 135
                     index_path = destdir / 'docs' / 'index.html'
    
    136 136
                     index_path.replace(dest / 'index.html')
    
    137
    +                pdfs = list(destdir.glob('*.pdf'))
    
    138
    +                for f in pdfs:
    
    139
    +                  f.replace(dest / f.name)
    
    137 140
                 elif job.name == 'hackage-doc-tarball':
    
    138 141
                     dest = dest_dir / 'hackage_docs'
    
    139 142
                     logging.info(f'moved hackage_docs to {dest}')
    

  • compiler/GHC/CmmToLlvm/Base.hs
    ... ... @@ -526,10 +526,10 @@ generateExternDecls = do
    526 526
       modifyEnv $ \env -> env { envAliases = emptyUniqSet }
    
    527 527
       return (concat defss, [])
    
    528 528
     
    
    529
    --- | Is a variable one of the special @$llvm@ globals?
    
    529
    +-- | Is a variable one of the special @\@llvm@ globals?
    
    530 530
     isBuiltinLlvmVar :: LlvmVar -> Bool
    
    531 531
     isBuiltinLlvmVar (LMGlobalVar lbl _ _ _ _ _) =
    
    532
    -    "$llvm" `isPrefixOf` unpackFS lbl
    
    532
    +    "llvm." `isPrefixOf` unpackFS lbl
    
    533 533
     isBuiltinLlvmVar _ = False
    
    534 534
     
    
    535 535
     -- | Here we take a global variable definition, rename it with a
    

  • compiler/GHC/Core/Opt/CprAnal.hs
    1
    +{-# LANGUAGE MultiWayIf #-}
    
    1 2
     
    
    2 3
     -- | Constructed Product Result analysis. Identifies functions that surely
    
    3 4
     -- return heap-allocated records on every code path, so that we can eliminate
    
    ... ... @@ -22,12 +23,15 @@ import GHC.Types.Demand
    22 23
     import GHC.Types.Cpr
    
    23 24
     import GHC.Types.Unique.MemoFun
    
    24 25
     
    
    26
    +import GHC.Core
    
    25 27
     import GHC.Core.FamInstEnv
    
    26 28
     import GHC.Core.DataCon
    
    27 29
     import GHC.Core.Type
    
    28 30
     import GHC.Core.Utils
    
    29
    -import GHC.Core
    
    31
    +import GHC.Core.Coercion
    
    32
    +import GHC.Core.Reduction
    
    30 33
     import GHC.Core.Seq
    
    34
    +import GHC.Core.TyCon
    
    31 35
     import GHC.Core.Opt.WorkWrap.Utils
    
    32 36
     
    
    33 37
     import GHC.Data.Graph.UnVar -- for UnVarSet
    
    ... ... @@ -216,9 +220,13 @@ cprAnal' _ (Type ty) = (topCprType, Type ty) -- Doesn't happen, in fact
    216 220
     cprAnal' _ (Coercion co) = (topCprType, Coercion co)
    
    217 221
     
    
    218 222
     cprAnal' env (Cast e co)
    
    219
    -  = (cpr_ty, Cast e' co)
    
    223
    +  = (cpr_ty', Cast e' co)
    
    220 224
       where
    
    221 225
         (cpr_ty, e') = cprAnal env e
    
    226
    +    cpr_ty'
    
    227
    +      | cpr_ty == topCprType                    = topCprType -- cheap case first
    
    228
    +      | isRecNewTyConApp env (coercionRKind co) = topCprType -- See Note [CPR for recursive data constructors]
    
    229
    +      | otherwise                               = cpr_ty
    
    222 230
     
    
    223 231
     cprAnal' env (Tick t e)
    
    224 232
       = (cpr_ty, Tick t e')
    
    ... ... @@ -384,6 +392,19 @@ cprTransformDataConWork env con args
    384 392
     mAX_CPR_SIZE :: Arity
    
    385 393
     mAX_CPR_SIZE = 10
    
    386 394
     
    
    395
    +isRecNewTyConApp :: AnalEnv -> Type -> Bool
    
    396
    +-- See Note [CPR for recursive newtype constructors]
    
    397
    +isRecNewTyConApp env ty
    
    398
    +  --- | pprTrace "isRecNewTyConApp" (ppr ty) False = undefined
    
    399
    +  | Just (tc, tc_args) <- splitTyConApp_maybe ty =
    
    400
    +      if | Just (HetReduction (Reduction _ rhs) _) <- topReduceTyFamApp_maybe (ae_fam_envs env) tc tc_args
    
    401
    +         -> isRecNewTyConApp env rhs
    
    402
    +         | Just dc <- newTyConDataCon_maybe tc
    
    403
    +         -> ae_rec_dc env dc == DefinitelyRecursive
    
    404
    +         | otherwise
    
    405
    +         -> False
    
    406
    +  | otherwise = False
    
    407
    +
    
    387 408
     --
    
    388 409
     -- * Bindings
    
    389 410
     --
    
    ... ... @@ -407,12 +428,18 @@ cprFix orig_env orig_pairs
    407 428
                    | otherwise    = orig_pairs
    
    408 429
         init_env = extendSigEnvFromIds orig_env (map fst init_pairs)
    
    409 430
     
    
    431
    +    -- If fixed-point iteration does not yield a result we use this instead
    
    432
    +    -- See Note [Safe abortion in the fixed-point iteration]
    
    433
    +    abort :: (AnalEnv, [(Id,CoreExpr)])
    
    434
    +    abort = step (nonVirgin orig_env) [(setIdCprSig id topCprSig, rhs) | (id, rhs) <- orig_pairs ]
    
    435
    +
    
    410 436
         -- The fixed-point varies the idCprSig field of the binders and and their
    
    411 437
         -- entries in the AnalEnv, and terminates if that annotation does not change
    
    412 438
         -- any more.
    
    413 439
         loop :: Int -> AnalEnv -> [(Id,CoreExpr)] -> (AnalEnv, [(Id,CoreExpr)])
    
    414 440
         loop n env pairs
    
    415 441
           | found_fixpoint = (reset_env', pairs')
    
    442
    +      | n == 10        = pprTraceUserWarning (text "cprFix aborts. This is not terrible, but worth reporting a GHC issue." <+> ppr (map fst pairs)) $ abort
    
    416 443
           | otherwise      = loop (n+1) env' pairs'
    
    417 444
           where
    
    418 445
             -- In all but the first iteration, delete the virgin flag
    
    ... ... @@ -511,8 +538,9 @@ cprAnalBind env id rhs
    511 538
         -- possibly trim thunk CPR info
    
    512 539
         rhs_ty'
    
    513 540
           -- See Note [CPR for thunks]
    
    514
    -      | stays_thunk = trimCprTy rhs_ty
    
    515
    -      | otherwise   = rhs_ty
    
    541
    +      | rhs_ty == topCprType = topCprType -- cheap case first
    
    542
    +      | stays_thunk          = trimCprTy rhs_ty
    
    543
    +      | otherwise            = rhs_ty
    
    516 544
         -- See Note [Arity trimming for CPR signatures]
    
    517 545
         sig  = mkCprSigForArity (idArity id) rhs_ty'
    
    518 546
         -- See Note [OPAQUE pragma]
    
    ... ... @@ -631,7 +659,7 @@ data AnalEnv
    631 659
       , ae_fam_envs :: FamInstEnvs
    
    632 660
       -- ^ Needed when expanding type families and synonyms of product types.
    
    633 661
       , ae_rec_dc :: DataCon -> IsRecDataConResult
    
    634
    -  -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataCon'
    
    662
    +  -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataType
    
    635 663
       }
    
    636 664
     
    
    637 665
     instance Outputable AnalEnv where
    
    ... ... @@ -1034,10 +1062,11 @@ Eliminating the shared 'c' binding in the process. And then
    1034 1062
     
    
    1035 1063
     What can we do about it?
    
    1036 1064
     
    
    1037
    - A. Don't CPR functions that return a *recursive data type* (the list in this
    
    1038
    -    case). This is the solution we adopt. Rationale: the benefit of CPR on
    
    1039
    -    recursive data structures is slight, because it only affects the outer layer
    
    1040
    -    of a potentially massive data structure.
    
    1065
    + A. Don't give recursive data constructors or casts representing recursive newtype constructors
    
    1066
    +    the CPR property (the list in this case). This is the solution we adopt.
    
    1067
    +    Rationale: the benefit of CPR on recursive data structures is slight,
    
    1068
    +    because it only affects the outer layer of a potentially massive data
    
    1069
    +    structure.
    
    1041 1070
      B. Don't CPR any *recursive function*. That would be quite conservative, as it
    
    1042 1071
         would also affect e.g. the factorial function.
    
    1043 1072
      C. Flat CPR only for recursive functions. This prevents the asymptotic
    
    ... ... @@ -1047,10 +1076,15 @@ What can we do about it?
    1047 1076
         `c` in the second eqn of `replicateC`). But we'd need to know which paths
    
    1048 1077
         were hot. We want such static branch frequency estimates in #20378.
    
    1049 1078
     
    
    1050
    -We adopt solution (A) It is ad-hoc, but appears to work reasonably well.
    
    1051
    -Deciding what a "recursive data constructor" is is quite tricky and ad-hoc, too:
    
    1052
    -See Note [Detecting recursive data constructors]. We don't have to be perfect
    
    1053
    -and can simply keep on unboxing if unsure.
    
    1079
    +We adopt solution (A). It is ad-hoc, but appears to work reasonably well.
    
    1080
    +Specifically:
    
    1081
    +
    
    1082
    +* For data constructors, in `cprTransformDataConWork` we check for a recursive
    
    1083
    +  data constructor by calling `ae_rec_dc env`, which is just a memoised version
    
    1084
    +  of `isRecDataCon`.  See Note [Detecting recursive data constructors]
    
    1085
    +* For newtypes, in the `Cast` case of `cprAnal`, we check for a recursive newtype
    
    1086
    +  by calling `isRecNewTyConApp`, which in turn calls `ae_rec_dc env`.
    
    1087
    +  See Note [CPR for recursive newtype constructors]
    
    1054 1088
     
    
    1055 1089
     Note [Detecting recursive data constructors]
    
    1056 1090
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1067,12 +1101,15 @@ looks inside the following class of types, represented by `ty` (and responds
    1067 1101
         types of its data constructors and check `tc_args` for recursion.
    
    1068 1102
      C. If `ty = F tc_args`, `F` is a `FamTyCon` and we can reduce `F tc_args` to
    
    1069 1103
         `rhs`, look into the `rhs` type.
    
    1104
    + D. If `ty = f a`, then look into `f` and `a`
    
    1105
    + E. If `ty = ty' |> co`, then look into `ty'`
    
    1070 1106
     
    
    1071 1107
     A few perhaps surprising points:
    
    1072 1108
     
    
    1073 1109
       1. It deems any function type as non-recursive, because it's unlikely that
    
    1074 1110
          a recursion through a function type builds up a recursive data structure.
    
    1075
    -  2. It doesn't look into kinds or coercion types because there's nothing to unbox.
    
    1111
    +  2. It doesn't look into kinds, literals or coercion types because we are
    
    1112
    +     ultimately looking for value-level recursion.
    
    1076 1113
          Same for promoted data constructors.
    
    1077 1114
       3. We don't care whether an AlgTyCon app `T tc_args` is fully saturated or not;
    
    1078 1115
          we simply look at its definition/DataCons and its field tys and look for
    
    ... ... @@ -1145,6 +1182,22 @@ I've played with the idea to make points (1) through (3) of 'isRecDataCon'
    1145 1182
     configurable like (4) to enable more re-use throughout the compiler, but haven't
    
    1146 1183
     found a killer app for that yet, so ultimately didn't do that.
    
    1147 1184
     
    
    1185
    +Note [CPR for recursive newtype constructors]
    
    1186
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1187
    +A newtype constructor is considered recursive iff the data constructor of the
    
    1188
    +equivalent datatype definition is recursive.
    
    1189
    +See Note [CPR for recursive data constructors].
    
    1190
    +Detection is a bit complicated by the fact that newtype constructor applications
    
    1191
    +reflect as Casts in Core:
    
    1192
    +
    
    1193
    +  newtype List a = C (Maybe (a, List a))
    
    1194
    +  xs = C (Just (0, C Nothing))
    
    1195
    +  ==> {desugar to Core}
    
    1196
    +  xs = Just (0, Nothing |> sym N:List) |> sym N:List
    
    1197
    +
    
    1198
    +So the check for `isRecNewTyConApp` is in the Cast case of `cprAnal` rather than
    
    1199
    +in `cprTransformDataConWork` as for data constructors.
    
    1200
    +
    
    1148 1201
     Note [CPR examples]
    
    1149 1202
     ~~~~~~~~~~~~~~~~~~~
    
    1150 1203
     Here are some examples (stranal/should_compile/T10482a) of the
    

  • compiler/GHC/Core/Opt/WorkWrap/Utils.hs
    ... ... @@ -63,6 +63,7 @@ import Data.List ( unzip4 )
    63 63
     
    
    64 64
     import GHC.Types.RepType
    
    65 65
     import GHC.Unit.Types
    
    66
    +import GHC.Core.TyCo.Rep
    
    66 67
     
    
    67 68
     {-
    
    68 69
     ************************************************************************
    
    ... ... @@ -1426,23 +1427,29 @@ isRecDataCon fam_envs fuel orig_dc
    1426 1427
                         | arg_ty <- map scaledThing (dataConRepArgTys dc) ]
    
    1427 1428
     
    
    1428 1429
         go_arg_ty :: IntWithInf -> TyConSet -> Type -> IsRecDataConResult
    
    1429
    -    go_arg_ty fuel visited_tcs ty
    
    1430
    -      --- | pprTrace "arg_ty" (ppr ty) False = undefined
    
    1430
    +    go_arg_ty fuel visited_tcs ty = -- pprTrace "arg_ty" (ppr ty) $
    
    1431
    +      case coreFullView ty of
    
    1432
    +        TyConApp tc tc_args -> go_tc_app fuel visited_tcs tc tc_args
    
    1433
    +          -- See Note [Detecting recursive data constructors], points (B) and (C)
    
    1431 1434
     
    
    1432
    -      | Just (_tcv, ty') <- splitForAllTyCoVar_maybe ty
    
    1433
    -      = go_arg_ty fuel visited_tcs ty'
    
    1435
    +        ForAllTy _ ty' -> go_arg_ty fuel visited_tcs ty'
    
    1434 1436
               -- See Note [Detecting recursive data constructors], point (A)
    
    1435 1437
     
    
    1436
    -      | Just (tc, tc_args) <- splitTyConApp_maybe ty
    
    1437
    -      = go_tc_app fuel visited_tcs tc tc_args
    
    1438
    +        CastTy ty' _ -> go_arg_ty fuel visited_tcs ty'
    
    1438 1439
     
    
    1439
    -      | otherwise
    
    1440
    -      = NonRecursiveOrUnsure
    
    1440
    +        AppTy f a -> go_arg_ty fuel visited_tcs f `combineIRDCR` go_arg_ty fuel visited_tcs a
    
    1441
    +          -- See Note [Detecting recursive data constructors], point (D)
    
    1442
    +
    
    1443
    +        FunTy{} -> NonRecursiveOrUnsure
    
    1444
    +          -- See Note [Detecting recursive data constructors], point (1)
    
    1445
    +
    
    1446
    +        -- (TyVarTy{} | LitTy{} | CastTy{})
    
    1447
    +        _ -> NonRecursiveOrUnsure
    
    1441 1448
     
    
    1442 1449
         go_tc_app :: IntWithInf -> TyConSet -> TyCon -> [Type] -> IsRecDataConResult
    
    1443 1450
         go_tc_app fuel visited_tcs tc tc_args =
    
    1444 1451
           case tyConDataCons_maybe tc of
    
    1445
    -      --- | pprTrace "tc_app" (vcat [ppr tc, ppr tc_args]) False = undefined
    
    1452
    +        ---_ | pprTrace "tc_app" (vcat [ppr tc, ppr tc_args]) False -> undefined
    
    1446 1453
             _ | Just (HetReduction (Reduction _ rhs) _) <- topReduceTyFamApp_maybe fam_envs tc tc_args
    
    1447 1454
               -- This is the only place where we look at tc_args, which might have
    
    1448 1455
               -- See Note [Detecting recursive data constructors], point (C) and (5)
    

  • compiler/GHC/Driver/Errors/Ppr.hs
    ... ... @@ -276,7 +276,7 @@ instance Diagnostic DriverMessage where
    276 276
                 ++ llvmVersionStr supportedLlvmVersionLowerBound
    
    277 277
                 ++ " and "
    
    278 278
                 ++ llvmVersionStr supportedLlvmVersionUpperBound
    
    279
    -            ++ ") and reinstall GHC to make -fllvm work")
    
    279
    +            ++ ") and reinstall GHC to ensure -fllvm works")
    
    280 280
     
    
    281 281
       diagnosticReason = \case
    
    282 282
         DriverUnknownMessage m
    
    ... ... @@ -347,7 +347,7 @@ instance Diagnostic DriverMessage where
    347 347
         DriverInstantiationNodeInDependencyGeneration {}
    
    348 348
           -> ErrorWithoutFlag
    
    349 349
         DriverNoConfiguredLLVMToolchain
    
    350
    -      -> ErrorWithoutFlag
    
    350
    +      -> WarningWithoutFlag
    
    351 351
     
    
    352 352
       diagnosticHints = \case
    
    353 353
         DriverUnknownMessage m
    

  • compiler/GHC/Tc/Solver/Equality.hs
    ... ... @@ -193,12 +193,8 @@ zonkEqTypes ev eq_rel ty1 ty2
    193 193
             then tycon tc1 tys1 tys2
    
    194 194
             else bale_out ty1 ty2
    
    195 195
     
    
    196
    -    go ty1 ty2
    
    197
    -      | Just (ty1a, ty1b) <- tcSplitAppTyNoView_maybe ty1
    
    198
    -      , Just (ty2a, ty2b) <- tcSplitAppTyNoView_maybe ty2
    
    199
    -      = do { res_a <- go ty1a ty2a
    
    200
    -           ; res_b <- go ty1b ty2b
    
    201
    -           ; return $ combine_rev mkAppTy res_b res_a }
    
    196
    +    -- If you are temppted to add a case for AppTy/AppTy, be careful
    
    197
    +    -- See Note [zonkEqTypes and the PKTI]
    
    202 198
     
    
    203 199
         go ty1@(LitTy lit1) (LitTy lit2)
    
    204 200
           | lit1 == lit2
    
    ... ... @@ -274,6 +270,32 @@ zonkEqTypes ev eq_rel ty1 ty2
    274 270
         combine_rev f (Right tys) (Right ty) = Right (f ty tys)
    
    275 271
     
    
    276 272
     
    
    273
    +{- Note [zonkEqTypes and the PKTI]
    
    274
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    275
    +Because `zonkEqTypes` does /partial/ zonking, we need to be very careful
    
    276
    +to maintain the Purely Kinded Type Invariant: see GHC.Tc.Gen/HsType
    
    277
    +HsNote [The Purely Kinded Type Invariant (PKTI)].
    
    278
    +
    
    279
    +In #26256 we try to solve this equality constraint:
    
    280
    +   Int :-> Maybe Char ~# k0 Int (m0 Char)
    
    281
    +where m0 and k0 are unification variables, and
    
    282
    +   m0 :: Type -> Type
    
    283
    +It happens that m0 was already unified
    
    284
    +   m0 := (w0 :: kappa)
    
    285
    +where kappa is another unification variable that is also already unified:
    
    286
    +   kappa := Type->Type.
    
    287
    +So the original type satisifed the PKTI, but a partially-zonked form
    
    288
    +   k0 Int (w0 Char)
    
    289
    +does not!! (This a bit reminiscent of Note [mkAppTyM].)
    
    290
    +
    
    291
    +The solution I have adopted is simply to make `zonkEqTypes` bale out on `AppTy`.
    
    292
    +After all, it's only supposed to be a quick hack to see if two types are already
    
    293
    +equal; if we bale out we'll just get into the "proper" canonicaliser.
    
    294
    +
    
    295
    +The only tricky thing about this approach is that it relies on /omitting/
    
    296
    +code -- for the AppTy/AppTy case!  Hence this Note
    
    297
    +-}
    
    298
    +
    
    277 299
     {- *********************************************************************
    
    278 300
     *                                                                      *
    
    279 301
     *           canonicaliseEquality
    

  • configure.ac
    ... ... @@ -351,15 +351,23 @@ fi
    351 351
     
    
    352 352
     dnl ** Building a cross compiler?
    
    353 353
     dnl --------------------------------------------------------------
    
    354
    -CrossCompiling=NO
    
    355
    -# If 'host' and 'target' differ, then this means we are building a cross-compiler.
    
    356
    -if test "$target" != "$host" ; then
    
    357
    -    CrossCompiling=YES
    
    358
    -    cross_compiling=yes   # This tells configure that it can accept just 'target',
    
    359
    -                          # otherwise you get
    
    360
    -                          #   configure: error: cannot run C compiled programs.
    
    361
    -                          #   If you meant to cross compile, use `--host'.
    
    354
    +dnl We allow the user to override this since the target/host check
    
    355
    +dnl can get this wrong in some particular cases. See #26236.
    
    356
    +if test -z "$CrossCompiling" ; then
    
    357
    +    CrossCompiling=NO
    
    358
    +    # If 'host' and 'target' differ, then this means we are building a cross-compiler.
    
    359
    +    if test "$target" != "$host" ; then
    
    360
    +        CrossCompiling=YES
    
    361
    +    fi
    
    362
    +fi
    
    363
    +if test "$CrossCompiling" = "YES"; then
    
    364
    +    # This tells configure that it can accept just 'target',
    
    365
    +    # otherwise you get
    
    366
    +    #   configure: error: cannot run C compiled programs.
    
    367
    +    #   If you meant to cross compile, use `--host'.
    
    368
    +    cross_compiling=yes
    
    362 369
     fi
    
    370
    +
    
    363 371
     if test "$BuildPlatform" != "$HostPlatform" ; then
    
    364 372
        AC_MSG_ERROR([
    
    365 373
     You've selected:
    

  • libraries/base/changelog.md
    1 1
     # Changelog for [`base` package](http://hackage.haskell.org/package/base)
    
    2 2
     
    
    3
    +## 4.21.2.0 *Sept 2024*
    
    4
    +  * Fix bug where `naturalAndNot` was incorrectly truncating results ([CLC proposal #350](github.com/haskell/core-libraries-committee/issues/350))
    
    5
    +
    
    3 6
     ## 4.21.1.0 *Sept 2024*
    
    4 7
       * Fix incorrect results of `integerPowMod` when the base is 0 and the exponent is negative, and `integerRecipMod` when the modulus is zero ([#26017](https://gitlab.haskell.org/ghc/ghc/-/issues/26017)).
    
    5 8
     
    

  • libraries/ghc-bignum/changelog.md
    ... ... @@ -4,6 +4,7 @@
    4 4
     
    
    5 5
     - Expose backendName
    
    6 6
     - Add `naturalSetBit[#]` (#21173), `naturalClearBit[#]` (#21175), `naturalComplementBit[#]` (#21181)
    
    7
    +- Fix bug where `naturalAndNot` was incorrectly truncating results (#26230)
    
    7 8
     
    
    8 9
     ## 1.2
    
    9 10
     
    

  • libraries/ghc-bignum/src/GHC/Num/Natural.hs
    ... ... @@ -488,7 +488,7 @@ naturalAndNot :: Natural -> Natural -> Natural
    488 488
     {-# NOINLINE naturalAndNot #-}
    
    489 489
     naturalAndNot (NS n) (NS m) = NS (n `and#` not# m)
    
    490 490
     naturalAndNot (NS n) (NB m) = NS (n `and#` not# (bigNatToWord# m))
    
    491
    -naturalAndNot (NB n) (NS m) = NS (bigNatToWord# n `and#` not# m)
    
    491
    +naturalAndNot (NB n) (NS m) = NB (bigNatAndNotWord# n m)
    
    492 492
     naturalAndNot (NB n) (NB m) = naturalFromBigNat# (bigNatAndNot n m)
    
    493 493
     
    
    494 494
     naturalOr :: Natural -> Natural -> Natural
    

  • rts/Messages.c
    ... ... @@ -180,13 +180,22 @@ uint32_t messageBlackHole(Capability *cap, MessageBlackHole *msg)
    180 180
             bh_info != &stg_CAF_BLACKHOLE_info &&
    
    181 181
             bh_info != &__stg_EAGER_BLACKHOLE_info &&
    
    182 182
             bh_info != &stg_WHITEHOLE_info) {
    
    183
    -        // if it is a WHITEHOLE, then a thread is in the process of
    
    184
    -        // trying to BLACKHOLE it.  But we know that it was once a
    
    185
    -        // BLACKHOLE, so there is at least a valid pointer in the
    
    186
    -        // payload, so we can carry on.
    
    187 183
             return 0;
    
    188 184
         }
    
    189 185
     
    
    186
    +    // If we see a WHITEHOLE then we should wait for it to turn into a BLACKHOLE.
    
    187
    +    // Otherwise we might look at the indirectee and segfault.
    
    188
    +    // See "Exception handling" in Note [Thunks, blackholes, and indirections]
    
    189
    +    // We might be looking at a *fresh* THUNK being WHITEHOLE-d so we can't
    
    190
    +    // guarantee that the indirectee is a valid pointer.
    
    191
    +#if defined(THREADED_RTS)
    
    192
    +    if (bh_info == &stg_WHITEHOLE_info) {
    
    193
    +      while(ACQUIRE_LOAD(&bh->header.info) == &stg_WHITEHOLE_info) {
    
    194
    +        busy_wait_nop();
    
    195
    +      }
    
    196
    +    }
    
    197
    +#endif
    
    198
    +
    
    190 199
         // The blackhole must indirect to a TSO, a BLOCKING_QUEUE, an IND,
    
    191 200
         // or a value.
    
    192 201
         StgClosure *p;
    

  • rts/StgMiscClosures.cmm
    ... ... @@ -31,6 +31,7 @@ import CLOSURE ENT_VIA_NODE_ctr;
    31 31
     import CLOSURE RtsFlags;
    
    32 32
     import CLOSURE stg_BLOCKING_QUEUE_CLEAN_info;
    
    33 33
     import CLOSURE stg_BLOCKING_QUEUE_DIRTY_info;
    
    34
    +import CLOSURE stg_END_TSO_QUEUE_closure;
    
    34 35
     import CLOSURE stg_IND_info;
    
    35 36
     import CLOSURE stg_MSG_BLACKHOLE_info;
    
    36 37
     import CLOSURE stg_TSO_info;
    
    ... ... @@ -574,6 +575,9 @@ retry:
    574 575
     
    
    575 576
             MessageBlackHole_tso(msg) = CurrentTSO;
    
    576 577
             MessageBlackHole_bh(msg) = node;
    
    578
    +        // Ensure that the link field is a valid closure,
    
    579
    +        // since we might turn this into an indirection in wakeBlockingQueue()
    
    580
    +        MessageBlackHole_link(msg) = stg_END_TSO_QUEUE_closure;
    
    577 581
             SET_HDR(msg, stg_MSG_BLACKHOLE_info, CCS_SYSTEM);
    
    578 582
             // messageBlackHole has appropriate memory barriers when this object is exposed.
    
    579 583
             // See Note [Heap memory barriers].
    

  • rts/Updates.h
    ... ... @@ -333,6 +333,10 @@
    333 333
      * `AP_STACK` closure recording the aborted execution state.
    
    334 334
      * See `RaiseAsync.c:raiseAsync` for details.
    
    335 335
      *
    
    336
    + * This can combine with indirection shortcutting during GC to replace a BLACKHOLE
    
    337
    + * with a fresh THUNK. We should be very careful here since the THUNK will have an
    
    338
    + * undefined value in the indirectee field. Looking at the indirectee field can then
    
    339
    + * lead to a segfault such as #26205.
    
    336 340
      *
    
    337 341
      * CAFs
    
    338 342
      * ----
    

  • testsuite/tests/cpranal/sigs/T25944.hs
    1
    +{-# LANGUAGE UndecidableInstances, LambdaCase #-}
    
    2
    +
    
    3
    +-- | This file starts with a small reproducer for #25944 that is easy to debug
    
    4
    +-- and then continues with a much larger MWE that is faithful to the original
    
    5
    +-- issue.
    
    6
    +module T25944 (foo, bar, popMinOneT, popMinOne) where
    
    7
    +
    
    8
    +import Data.Functor.Identity ( Identity(..) )
    
    9
    +import Data.Coerce
    
    10
    +
    
    11
    +data ListCons a b = Nil | a :- !b
    
    12
    +newtype Fix f = Fix (f (Fix f)) -- Rec
    
    13
    +
    
    14
    +foo :: Fix (ListCons a) -> Fix (ListCons a) -> Fix (ListCons a)
    
    15
    +foo a b = go a
    
    16
    +  where
    
    17
    +    -- The outer loop arranges it so that the base case `go as` of `go2` is
    
    18
    +    -- bottom on the first iteration of the loop.
    
    19
    +    go (Fix Nil) = Fix Nil
    
    20
    +    go (Fix (a :- as)) = Fix (a :- go2 b)
    
    21
    +      where
    
    22
    +        go2 (Fix Nil) = go as
    
    23
    +        go2 (Fix (b :- bs)) = Fix (b :- go2 bs)
    
    24
    +
    
    25
    +bar :: Int -> (Fix (ListCons Int), Int)
    
    26
    +bar n = (foo (Fix Nil) (Fix Nil), n) -- should still have CPR property
    
    27
    +
    
    28
    +-- Now the actual reproducer from #25944:
    
    29
    +
    
    30
    +newtype ListT m a = ListT { runListT :: m (ListCons a (ListT m a)) }
    
    31
    +
    
    32
    +cons :: Applicative m => a -> ListT m a -> ListT m a
    
    33
    +cons x xs = ListT (pure (x :- xs))
    
    34
    +
    
    35
    +nil :: Applicative m => ListT m a
    
    36
    +nil = ListT (pure Nil)
    
    37
    +
    
    38
    +instance Functor m => Functor (ListT m) where
    
    39
    +  fmap f (ListT m) = ListT (go <$> m)
    
    40
    +     where
    
    41
    +       go Nil = Nil
    
    42
    +       go (a :- m) = f a :- (f <$> m)
    
    43
    +
    
    44
    +foldListT :: ((ListCons a (ListT m a) -> c) -> m (ListCons a (ListT m a)) -> b)
    
    45
    +          -> (a -> b -> c)
    
    46
    +          -> c
    
    47
    +          -> ListT m a -> b
    
    48
    +foldListT r c n = r h . runListT
    
    49
    +  where
    
    50
    +    h Nil = n
    
    51
    +    h (x :- ListT xs) = c x (r h xs)
    
    52
    +{-# INLINE foldListT #-}
    
    53
    +
    
    54
    +mapListT :: forall a m b. Monad m => (a -> ListT m b -> ListT m b) -> ListT m b -> ListT m a -> ListT m b
    
    55
    +mapListT =
    
    56
    +  foldListT
    
    57
    +  ((coerce ::
    
    58
    + ((ListCons a (ListT m a) -> m (ListCons b (ListT m b))) -> m (ListCons a (ListT m a)) -> m (ListCons b (ListT m b))) ->
    
    59
    + ((ListCons a (ListT m a) -> ListT m b) -> m (ListCons a (ListT m a)) -> ListT m b))
    
    60
    +  (=<<))
    
    61
    +{-# INLINE mapListT #-}
    
    62
    +
    
    63
    +instance Monad m => Applicative (ListT m) where
    
    64
    +  pure x = cons x nil
    
    65
    +  {-# INLINE pure #-}
    
    66
    +  liftA2 f xs ys = mapListT (\x zs -> mapListT (cons . f x) zs ys) nil xs
    
    67
    +  {-# INLINE liftA2 #-}
    
    68
    +
    
    69
    +instance Monad m => Monad (ListT m) where
    
    70
    +  xs >>= f = mapListT (flip (mapListT cons) . f) nil xs
    
    71
    +  {-# INLINE (>>=) #-}
    
    72
    +
    
    73
    +infixr 5 :<
    
    74
    +data Node w a b = Leaf a | !w :< b
    
    75
    +  deriving (Functor)
    
    76
    +
    
    77
    +bimapNode f g (Leaf x) = Leaf (f x)
    
    78
    +bimapNode f g (x :< xs) = x :< g xs
    
    79
    +
    
    80
    +newtype HeapT w m a = HeapT { runHeapT :: ListT m (Node w a (HeapT w m a)) }
    
    81
    +
    
    82
    +-- | The 'Heap' type, specialised to the 'Identity' monad.
    
    83
    +type Heap w = HeapT w Identity
    
    84
    +
    
    85
    +instance Functor m => Functor (HeapT w m) where
    
    86
    +  fmap f = HeapT . fmap (bimapNode f (fmap f)) . runHeapT
    
    87
    +
    
    88
    +instance Monad m => Applicative (HeapT w m) where
    
    89
    +  pure = HeapT . pure . Leaf
    
    90
    +  (<*>) = liftA2 id
    
    91
    +
    
    92
    +instance Monad m => Monad (HeapT w m) where
    
    93
    +  HeapT m >>= f = HeapT (m >>= g)
    
    94
    +    where
    
    95
    +      g (Leaf x) = runHeapT (f x)
    
    96
    +      g (w :< xs) = pure (w :< (xs >>= f))
    
    97
    +
    
    98
    +popMinOneT :: forall w m a. (Monoid w, Monad m) => HeapT w m a -> m (Maybe ((a, w), HeapT w m a))
    
    99
    +popMinOneT = go mempty [] . runHeapT
    
    100
    +  where
    
    101
    +    go' :: w -> Maybe (w, HeapT w m a) -> m (Maybe ((a, w), HeapT w m a))
    
    102
    +    go' a Nothing = pure Nothing
    
    103
    +    go' a (Just (w, HeapT xs)) = go (a <> w) [] xs
    
    104
    +
    
    105
    +    go :: w -> [(w, HeapT w m a)] -> ListT m (Node w a (HeapT w m a)) -> m (Maybe ((a, w), HeapT w m a))
    
    106
    +    go w a (ListT xs) = xs >>= \case
    
    107
    +      Nil -> go' w (undefined)
    
    108
    +      Leaf x :- xs -> pure (Just ((x, w), undefined >> HeapT (foldl (\ys (yw,y) -> ListT (pure ((yw :< y) :- ys))) xs a)))
    
    109
    +      (u :< x) :- xs -> go w ((u,x) : a) xs
    
    110
    +{-# INLINE popMinOneT #-}
    
    111
    +
    
    112
    +popMinOne :: Monoid w => Heap w a -> Maybe ((a, w), Heap w a)
    
    113
    +popMinOne = runIdentity . popMinOneT
    
    114
    +{-# INLINE popMinOne #-}

  • testsuite/tests/cpranal/sigs/T25944.stderr
    1
    +
    
    2
    +==================== Cpr signatures ====================
    
    3
    +T25944.$fApplicativeHeapT:
    
    4
    +T25944.$fApplicativeListT:
    
    5
    +T25944.$fFunctorHeapT:
    
    6
    +T25944.$fFunctorListT:
    
    7
    +T25944.$fFunctorNode:
    
    8
    +T25944.$fMonadHeapT:
    
    9
    +T25944.$fMonadListT:
    
    10
    +T25944.bar: 1
    
    11
    +T25944.foo:
    
    12
    +T25944.popMinOne: 2(1(1,))
    
    13
    +T25944.popMinOneT:
    
    14
    +T25944.runHeapT:
    
    15
    +T25944.runListT:
    
    16
    +
    
    17
    +

  • testsuite/tests/cpranal/sigs/all.T
    ... ... @@ -12,3 +12,4 @@ test('T16040', normal, compile, [''])
    12 12
     test('T19232', normal, compile, [''])
    
    13 13
     test('T19398', normal, compile, [''])
    
    14 14
     test('T19822', normal, compile, [''])
    
    15
    +test('T25944', normal, compile, [''])

  • testsuite/tests/numeric/should_run/T26230.hs
    1
    +import Data.Bits
    
    2
    +import GHC.Num.Natural
    
    3
    +
    
    4
    +main = do
    
    5
    +  print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) (2 ^ 3)
    
    6
    +  print $ naturalAndNot ((2 ^ 129) .|. (2 ^ 65)) (2 ^ 65)
    
    7
    +  print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) ((2 ^ 65) .|. (2 ^ 3))
    
    8
    +  print $ naturalAndNot ((2 ^ 65) .|. (2 ^ 3)) (2 ^ 3)

  • testsuite/tests/numeric/should_run/T26230.stdout
    1
    +16
    
    2
    +680564733841876926926749214863536422912
    
    3
    +16
    
    4
    +36893488147419103232

  • testsuite/tests/numeric/should_run/all.T
    ... ... @@ -87,3 +87,4 @@ test('T24066', normal, compile_and_run, [''])
    87 87
     test('div01', normal, compile_and_run, [''])
    
    88 88
     test('T24245', normal, compile_and_run, [''])
    
    89 89
     test('T25653', normal, compile_and_run, [''])
    
    90
    +test('T26230', normal, compile_and_run, [''])

  • testsuite/tests/partial-sigs/should_compile/T26256.hs
    1
    +{-# LANGUAGE GHC2021 #-}
    
    2
    +{-# LANGUAGE TypeFamilies #-}
    
    3
    +{-# LANGUAGE PartialTypeSignatures #-}
    
    4
    +
    
    5
    +module M (go) where
    
    6
    +
    
    7
    +import Data.Kind
    
    8
    +
    
    9
    +type Apply :: (Type -> Type) -> Type
    
    10
    +data Apply m
    
    11
    +
    
    12
    +type (:->) :: Type -> Type -> Type
    
    13
    +type family (:->) where (:->) = (->)
    
    14
    +
    
    15
    +f :: forall (k :: Type -> Type -> Type) (m :: Type -> Type).
    
    16
    +     k Int (m Char) -> k Bool (Apply m)
    
    17
    +f = f
    
    18
    +
    
    19
    +x :: Int :-> Maybe Char
    
    20
    +x = x
    
    21
    +
    
    22
    +go :: Bool -> _ _
    
    23
    +go = f x

  • testsuite/tests/partial-sigs/should_compile/T26256.stderr
    1
    +T26256.hs:22:15: warning: [GHC-88464] [-Wpartial-type-signatures (in -Wdefault)]
    
    2
    +    • Found type wildcard ‘_’ standing for ‘Apply :: (* -> *) -> *’
    
    3
    +    • In the type signature: go :: Bool -> _ _
    
    4
    +
    
    5
    +T26256.hs:22:17: warning: [GHC-88464] [-Wpartial-type-signatures (in -Wdefault)]
    
    6
    +    • Found type wildcard ‘_’ standing for ‘Maybe :: * -> *’
    
    7
    +    • In the first argument of ‘_’, namely ‘_’
    
    8
    +      In the type signature: go :: Bool -> _ _

  • testsuite/tests/partial-sigs/should_compile/all.T
    ... ... @@ -108,3 +108,4 @@ test('T21667', normal, compile, [''])
    108 108
     test('T22065', normal, compile, [''])
    
    109 109
     test('T16152', normal, compile, [''])
    
    110 110
     test('T20076', expect_broken(20076), compile, [''])
    
    111
    +test('T26256', normal, compile, [''])

  • testsuite/tests/typecheck/should_compile/T26256a.hs
    1
    +{-# LANGUAGE GHC2021 #-}
    
    2
    +{-# LANGUAGE TypeFamilies #-}
    
    3
    +
    
    4
    +module T26256 (go) where
    
    5
    +
    
    6
    +import Data.Kind
    
    7
    +
    
    8
    +class Cat k where (<<<) :: k a b -> k x a -> k x b
    
    9
    +instance Cat (->) where (<<<) = (.)
    
    10
    +class Pro k p where pro :: k a b s t -> p a b -> p s t
    
    11
    +data Hiding o a b s t = forall e. Hiding (s -> o e a)
    
    12
    +newtype Apply e a = Apply (e a)
    
    13
    +
    
    14
    +type (:->) :: Type -> Type -> Type
    
    15
    +type family (:->) where
    
    16
    +  (:->) = (->)
    
    17
    +
    
    18
    +go :: (Pro (Hiding Apply) p) => (s :-> e a) -> p a b -> p s t
    
    19
    +go sea = pro (Hiding (Apply <<< sea))

  • testsuite/tests/typecheck/should_compile/all.T
    ... ... @@ -935,3 +935,4 @@ test('T24845a', normal, compile, [''])
    935 935
     test('T23501a', normal, compile, [''])
    
    936 936
     test('T23501b', normal, compile, [''])
    
    937 937
     test('T25597', normal, compile, [''])
    
    938
    +test('T26256a', normal, compile, [''])