Simon Peyton Jones pushed to branch wip/T27724 at Glasgow Haskell Compiler / GHC
Commits:
-
5b405cd7
by Simon Peyton Jones at 2026-09-10T17:08:46+01:00
12 changed files:
- compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/Tc/Instance/Class.hs
- libraries/ghc-internal/src/GHC/Internal/Magic.hs
- testsuite/tests/corelint/LintEtaExpand.hs
- utils/genprimopcode/Main.hs
Changes:
| ... | ... | @@ -18,13 +18,16 @@ module GHC.Builtin.WiredIn.Ids ( |
| 18 | 18 | wiredInIds, ghcPrimIds,
|
| 19 | 19 | realWorldPrimId,
|
| 20 | 20 | voidPrimId, voidArgId,
|
| 21 | - nullAddrId, seqId, lazyId, lazyIdKey,
|
|
| 22 | - coercionTokenId, coerceId,
|
|
| 23 | - proxyHashId,
|
|
| 21 | + nullAddrId, seqId, lazyId, lazyIdKey, proxyHashId,
|
|
| 22 | + coercionTokenId, coerceId, coerceName,
|
|
| 24 | 23 | nospecId, nospecIdName,
|
| 25 | - noinlineId, noinlineIdName,
|
|
| 26 | - noinlineConstraintId, noinlineConstraintIdName,
|
|
| 27 | - coerceName, leftSectionName, rightSectionName,
|
|
| 24 | + |
|
| 25 | + getNoinlineId, isNoinlineId,
|
|
| 26 | + noinlineId, noinlineIdName,
|
|
| 27 | + noinlineConstraintId, noinlineConstraintIdName,
|
|
| 28 | + |
|
| 29 | + leftSectionName, rightSectionName,
|
|
| 30 | + |
|
| 28 | 31 | pcRepPolyId,
|
| 29 | 32 | |
| 30 | 33 | unboxedUnitExpr,
|
| ... | ... | @@ -54,11 +57,14 @@ import GHC.Types.Name.Env |
| 54 | 57 | import GHC.Types.Id
|
| 55 | 58 | import GHC.Types.Id.Info
|
| 56 | 59 | import GHC.Types.InlinePragma
|
| 57 | -import GHC.Types.Var (VarBndr(Bndr), visArgConstraintLike, tyVarName)
|
|
| 60 | +import GHC.Types.Var (VarBndr(Bndr), invisArgConstraintLike, tyVarName)
|
|
| 61 | +import GHC.Types.Basic( TypeOrConstraint(..) )
|
|
| 58 | 62 | |
| 59 | 63 | import GHC.Tc.Types.Origin
|
| 60 | 64 | import GHC.Tc.Utils.TcType as TcType
|
| 61 | 65 | |
| 66 | +import GHC.Utils.Panic
|
|
| 67 | +import GHC.Utils.Outputable
|
|
| 62 | 68 | import GHC.Data.FastString
|
| 63 | 69 | |
| 64 | 70 | |
| ... | ... | @@ -92,7 +98,7 @@ that module's interface file; instead, the full definition is right |
| 92 | 98 | here.
|
| 93 | 99 | |
| 94 | 100 | Note [ghcPrimIds (aka pseudoops)]
|
| 95 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 101 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 96 | 102 | The ghcPrimIds
|
| 97 | 103 | |
| 98 | 104 | * Are exported from GHC.Prim (see ghcPrimExports, used in ghcPrimInterface)
|
| ... | ... | @@ -239,15 +245,15 @@ seqId = pcRepPolyId seqName ty concs info |
| 239 | 245 | -- seq :: forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b
|
| 240 | 246 | ty =
|
| 241 | 247 | mkInfForAllTy runtimeRep2TyVar
|
| 242 | - $ mkSpecForAllTys [alphaTyVar, openBetaTyVar]
|
|
| 243 | - $ mkVisFunTyMany alphaTy (mkVisFunTyMany openBetaTy openBetaTy)
|
|
| 248 | + $ mkSpecForAllTys [alphaTyVar, rrPolyTyVar2]
|
|
| 249 | + $ mkVisFunTyMany alphaTy (mkVisFunTyMany rrPolyTy2 rrPolyTy2)
|
|
| 244 | 250 | |
| 245 | - [x,y] = mkTemplateLocals [alphaTy, openBetaTy]
|
|
| 246 | - rhs = mkLams ([runtimeRep2TyVar, alphaTyVar, openBetaTyVar, x, y]) $
|
|
| 247 | - Case (Var x) x openBetaTy [Alt DEFAULT [] (Var y)]
|
|
| 251 | + [x,y] = mkTemplateLocals [rrPolyTy1, rrPolyTy2]
|
|
| 252 | + rhs = mkLams ([runtimeRep2TyVar, alphaTyVar, rrPolyTyVar2, x, y]) $
|
|
| 253 | + Case (Var x) x rrPolyTy2 [Alt DEFAULT [] (Var y)]
|
|
| 248 | 254 | |
| 249 | 255 | concs = mkRepPolyIdConcreteTyVars
|
| 250 | - [ ((openBetaTy, mkArgPos 2 Top), runtimeRep2TyVar)]
|
|
| 256 | + [ ((rrPolyTy2, mkArgPos 2 Top), runtimeRep2TyVar)]
|
|
| 251 | 257 | |
| 252 | 258 | arity = 2
|
| 253 | 259 | |
| ... | ... | @@ -271,15 +277,27 @@ noinlineId = pcMiscPrelId noinlineIdName ty info |
| 271 | 277 | info = noCafIdInfo
|
| 272 | 278 | -- noinline :: forall r (a :: TYPE r). a -> a
|
| 273 | 279 | ty = mkInfForAllTy runtimeRep1TyVar $
|
| 274 | - mkSpecForAllTys [openAlphaTyVar] $
|
|
| 275 | - mkVisFunTyMany openAlphaTy openAlphaTy
|
|
| 280 | + mkSpecForAllTys [rrPolyTyVar1] $
|
|
| 281 | + mkVisFunTyMany rrPolyTy1 rrPolyTy1
|
|
| 276 | 282 | |
| 277 | 283 | noinlineConstraintId :: Id -- See Note [noinlineId magic]
|
| 278 | 284 | noinlineConstraintId = pcMiscPrelId noinlineConstraintIdName ty info
|
| 279 | 285 | where
|
| 280 | 286 | info = noCafIdInfo
|
| 281 | - ty = mkSpecForAllTys [alphaConstraintTyVar] $
|
|
| 282 | - mkFunTy visArgConstraintLike ManyTy alphaTy alphaConstraintTy
|
|
| 287 | + ty = mkInfForAllTy runtimeRep1TyVar $
|
|
| 288 | + mkSpecForAllTys [rrPolyConstraintVar1] $
|
|
| 289 | + mkFunTy invisArgConstraintLike ManyTy rrPolyConstraintTy1 rrPolyConstraintTy1
|
|
| 290 | + |
|
| 291 | +isNoinlineId :: Id -> Bool
|
|
| 292 | +isNoinlineId fn = key == noinlineIdKey || key == noinlineConstraintIdKey
|
|
| 293 | + where
|
|
| 294 | + key = getUnique fn
|
|
| 295 | + |
|
| 296 | +getNoinlineId :: Type -> (Id, RuntimeRepType)
|
|
| 297 | +getNoinlineId ty = case sORTKind_maybe (typeKind ty) of
|
|
| 298 | + Just (TypeLike, rep) -> (noinlineId, rep)
|
|
| 299 | + Just (ConstraintLike, rep) -> (noinlineConstraintId, rep)
|
|
| 300 | + Nothing -> pprPanic "getNoinlineId" (ppr ty)
|
|
| 283 | 301 | |
| 284 | 302 | ------------------------------------------------
|
| 285 | 303 | nospecId :: Id -- See Note [nospecId magic]
|
| ... | ... | @@ -296,19 +314,19 @@ oneShotId = pcRepPolyId oneShotName ty concs info |
| 296 | 314 | `setArityInfo` arity
|
| 297 | 315 | -- oneShot :: forall {r1 r2} (a :: TYPE r1) (b :: TYPE r2). (a -> b) -> (a -> b)
|
| 298 | 316 | ty = mkInfForAllTys [ runtimeRep1TyVar, runtimeRep2TyVar ] $
|
| 299 | - mkSpecForAllTys [ openAlphaTyVar, openBetaTyVar ] $
|
|
| 317 | + mkSpecForAllTys [ rrPolyTyVar1, rrPolyTyVar2 ] $
|
|
| 300 | 318 | mkVisFunTyMany fun_ty fun_ty
|
| 301 | - fun_ty = mkVisFunTyMany openAlphaTy openBetaTy
|
|
| 302 | - [body, x] = mkTemplateLocals [fun_ty, openAlphaTy]
|
|
| 319 | + fun_ty = mkVisFunTyMany rrPolyTy1 rrPolyTy2
|
|
| 320 | + [body, x] = mkTemplateLocals [fun_ty, rrPolyTy1]
|
|
| 303 | 321 | x' = setOneShotLambda x -- Here is the magic bit!
|
| 304 | 322 | rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar
|
| 305 | - , openAlphaTyVar, openBetaTyVar
|
|
| 323 | + , rrPolyTyVar1, rrPolyTyVar2
|
|
| 306 | 324 | , body, x'] $
|
| 307 | 325 | Var body `App` Var x'
|
| 308 | 326 | arity = 2
|
| 309 | 327 | |
| 310 | 328 | concs = mkRepPolyIdConcreteTyVars
|
| 311 | - [((openAlphaTy, mkArgPos 2 Top), runtimeRep1TyVar)]
|
|
| 329 | + [((rrPolyTy1, mkArgPos 2 Top), runtimeRep1TyVar)]
|
|
| 312 | 330 | |
| 313 | 331 | ----------------------------------------------------------------------
|
| 314 | 332 | {- Note [Wired-in Ids for rebindable syntax]
|
| ... | ... | @@ -340,20 +358,20 @@ leftSectionId = pcRepPolyId leftSectionName ty concs info |
| 340 | 358 | `setUnfoldingInfo` mkCompulsoryUnfolding rhs
|
| 341 | 359 | `setArityInfo` arity
|
| 342 | 360 | ty = mkInfForAllTys [runtimeRep1TyVar,runtimeRep2TyVar, multiplicityTyVar1] $
|
| 343 | - mkSpecForAllTys [openAlphaTyVar, openBetaTyVar] $
|
|
| 361 | + mkSpecForAllTys [rrPolyTyVar1, rrPolyTyVar2] $
|
|
| 344 | 362 | exprType body
|
| 345 | - [f,x] = mkTemplateLocals [mkVisFunTy mult openAlphaTy openBetaTy, openAlphaTy]
|
|
| 363 | + [f,x] = mkTemplateLocals [mkVisFunTy mult rrPolyTy1 rrPolyTy2, rrPolyTy1]
|
|
| 346 | 364 | |
| 347 | 365 | mult = mkTyVarTy multiplicityTyVar1 :: Mult
|
| 348 | 366 | xmult = setIdMult x mult
|
| 349 | 367 | |
| 350 | 368 | rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar, multiplicityTyVar1
|
| 351 | - , openAlphaTyVar, openBetaTyVar ] body
|
|
| 369 | + , rrPolyTyVar1, rrPolyTyVar2 ] body
|
|
| 352 | 370 | body = mkLams [f,xmult] $ App (Var f) (Var xmult)
|
| 353 | 371 | arity = 2
|
| 354 | 372 | |
| 355 | 373 | concs = mkRepPolyIdConcreteTyVars
|
| 356 | - [((openAlphaTy, mkArgPos 2 Top), runtimeRep1TyVar)]
|
|
| 374 | + [((rrPolyTy1, mkArgPos 2 Top), runtimeRep1TyVar)]
|
|
| 357 | 375 | |
| 358 | 376 | -- See Note [Left and right sections] in GHC.Rename.Expr
|
| 359 | 377 | -- See Note [Wired-in Ids for rebindable syntax]
|
| ... | ... | @@ -369,26 +387,26 @@ rightSectionId = pcRepPolyId rightSectionName ty concs info |
| 369 | 387 | `setArityInfo` arity
|
| 370 | 388 | ty = mkInfForAllTys [runtimeRep1TyVar,runtimeRep2TyVar,runtimeRep3TyVar
|
| 371 | 389 | , multiplicityTyVar1, multiplicityTyVar2 ] $
|
| 372 | - mkSpecForAllTys [openAlphaTyVar, openBetaTyVar, openGammaTyVar ] $
|
|
| 390 | + mkSpecForAllTys [rrPolyTyVar1, rrPolyTyVar2, rrPolyTyVar3] $
|
|
| 373 | 391 | exprType body
|
| 374 | 392 | mult1 = mkTyVarTy multiplicityTyVar1
|
| 375 | 393 | mult2 = mkTyVarTy multiplicityTyVar2
|
| 376 | 394 | |
| 377 | - [f,x,y] = mkTemplateLocals [ mkScaledFunTys [ Scaled mult1 openAlphaTy
|
|
| 378 | - , Scaled mult2 openBetaTy ] openGammaTy
|
|
| 379 | - , openAlphaTy, openBetaTy ]
|
|
| 395 | + [f,x,y] = mkTemplateLocals [ mkScaledFunTys [ Scaled mult1 rrPolyTy1
|
|
| 396 | + , Scaled mult2 rrPolyTy2 ] rrPolyTy3
|
|
| 397 | + , rrPolyTy1, rrPolyTy2 ]
|
|
| 380 | 398 | xmult = setIdMult x mult1
|
| 381 | 399 | ymult = setIdMult y mult2
|
| 382 | 400 | rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar, runtimeRep3TyVar
|
| 383 | 401 | , multiplicityTyVar1, multiplicityTyVar2
|
| 384 | - , openAlphaTyVar, openBetaTyVar, openGammaTyVar ] body
|
|
| 402 | + , rrPolyTyVar1, rrPolyTyVar2, rrPolyTyVar3 ] body
|
|
| 385 | 403 | body = mkLams [f,ymult,xmult] $ mkVarApps (Var f) [xmult,ymult]
|
| 386 | 404 | arity = 3
|
| 387 | 405 | |
| 388 | 406 | concs =
|
| 389 | 407 | mkRepPolyIdConcreteTyVars
|
| 390 | - [ ((openAlphaTy, mkArgPos 3 Top), runtimeRep1TyVar)
|
|
| 391 | - , ((openBetaTy , mkArgPos 2 Top), runtimeRep2TyVar)]
|
|
| 408 | + [ ((rrPolyTy1, mkArgPos 3 Top), runtimeRep1TyVar)
|
|
| 409 | + , ((rrPolyTy2, mkArgPos 2 Top), runtimeRep2TyVar)]
|
|
| 392 | 410 | |
| 393 | 411 | --------------------------------------------------------------------------------
|
| 394 | 412 | |
| ... | ... | @@ -521,55 +539,55 @@ Implementing 'lazy' is a bit tricky: |
| 521 | 539 | |
| 522 | 540 | Note [noinlineId magic]
|
| 523 | 541 | ~~~~~~~~~~~~~~~~~~~~~~~
|
| 524 | -'noinline' is used to make sure that a function f is never inlined,
|
|
| 525 | -e.g., as in 'noinline f x'. We won't inline f because we never inline
|
|
| 526 | -lone variables (see Note [Lone variables] in GHC.Core.Unfold
|
|
| 542 | +'noinline' is used to make sure that a function f is never inlined, e.g
|
|
| 543 | + noinline f x
|
|
| 544 | + noinline (f x)
|
|
| 545 | +Both of these will work. Here are the moving parts:
|
|
| 527 | 546 | |
| 528 | -You might think that we could implement noinline like this:
|
|
| 529 | - {-# NOINLINE #-}
|
|
| 530 | - noinline :: forall a. a -> a
|
|
| 531 | - noinline x = x
|
|
| 547 | +* `noinline` is magic Id (see Note [magicIds]), whose wired-in behaviour is
|
|
| 548 | + defined in this module, GHC.Builtin.WiredIn.Ids.
|
|
| 532 | 549 | |
| 533 | -But actually we give 'noinline' a wired-in name for three distinct reasons:
|
|
| 550 | +* In the Simplifier, see the `isNoInlineId` case of `simplOutId`.
|
|
| 551 | + When we encounter noinline (f e1 e2) e3 e4:
|
|
| 552 | + * We switch off inlining before simplifying `f` (#18995)
|
|
| 553 | + * We slide `e3` and `e4` under the `noinline` to give
|
|
| 554 | + noinline (f e1 e2 e3 e4)
|
|
| 555 | + See wrinkle (NOI1)
|
|
| 534 | 556 | |
| 535 | -1. We don't want to leave a (useless) call to noinline in the final program,
|
|
| 536 | - to be executed at runtime. So we have a little bit of magic to
|
|
| 537 | - optimize away 'noinline' after we are done running the simplifier.
|
|
| 538 | - This is done in GHC.CoreToStg.Prep.cpeApp.
|
|
| 539 | - |
|
| 540 | -2. 'noinline' sometimes gets inserted automatically when we serialize an
|
|
| 541 | - expression to the interface format, in GHC.CoreToIface.toIfaceVar.
|
|
| 542 | - See Note [Inlining and hs-boot files] in GHC.CoreToIface
|
|
| 543 | - |
|
| 544 | -3. Given foo :: Eq a => [a] -> Bool, the expression
|
|
| 545 | - noinline foo x xs
|
|
| 546 | - where x::Int, will naturally desugar to
|
|
| 547 | - noinline @Int (foo @Int dEqInt) x xs
|
|
| 548 | - But now it's entirely possible that (foo @Int dEqInt) will inline foo,
|
|
| 549 | - since 'foo' is no longer a lone variable -- see #18995
|
|
| 550 | - |
|
| 551 | - Solution: in the desugarer, rewrite
|
|
| 552 | - noinline (f x y) ==> noinline f x y
|
|
| 553 | - This is done in the `noinlineId` case of `GHC.HsToCore.Expr.ds_app_var`
|
|
| 554 | - This is only needed for noinlineId, not noInlineConstraintId (wrinkle
|
|
| 555 | - (W1) below), because the latter never shows up in user code.
|
|
| 557 | +* In GHC.CoreToStg.Prep.cpe_app, we discard the `noinline`, so that
|
|
| 558 | + there is no runtime overhead.
|
|
| 556 | 559 | |
| 557 | 560 | Wrinkles
|
| 558 | 561 | |
| 559 | -(W1) Sometimes case (2) above needs to apply `noinline` to a type of kind
|
|
| 562 | +(NOI1) It's very important to have
|
|
| 563 | + noinline (f e1 e2) -- `f` visibly applied
|
|
| 564 | + and NOT
|
|
| 565 | + noinline f e1 e2 -- `f` is not applied
|
|
| 566 | + Because we want
|
|
| 567 | + * Strictness (#18396, #23911, #16588)
|
|
| 568 | + * Type-class specialisation (#27724)
|
|
| 569 | + * Rewrite rules
|
|
| 570 | + all to work, and they won't if `f` isn't applied to anything
|
|
| 571 | + |
|
| 572 | +(NOI2) `noinline` needs to apply to unboxed types, so that
|
|
| 573 | + noinline (f x y)
|
|
| 574 | + works even if `f` happens to return Int#. So
|
|
| 575 | + noinline :: forall (r::RuntimeRep) (a::TYPE r). a -> a
|
|
| 576 | + |
|
| 577 | +(NOI3) Very trickily, 'noinline' sometimes gets inserted automatically when we
|
|
| 578 | + serialize an expression to the interface format, in `GHC.CoreToIface.toIfaceVar`.
|
|
| 579 | + See Note [Inlining and hs-boot files] in GHC.CoreToIface
|
|
| 580 | + |
|
| 581 | +(NOI4) Sometimes case (NOI3) needs to apply `noinline` to a type of kind
|
|
| 560 | 582 | Constraint; e.g.
|
| 561 | 583 | noinline @(Eq Int) $dfEqInt
|
| 562 | - We don't have type-or-kind polymorphism, so we simply have two `inline`
|
|
| 563 | - Ids, namely `noinlineId` and `noinlineConstraintId`.
|
|
| 564 | - |
|
| 565 | -(W2) Note that noinline as currently implemented can hide some simplifications
|
|
| 566 | - since it hides strictness from the demand analyser. Specifically, the
|
|
| 567 | - demand analyser will treat 'noinline f x' as lazy in 'x', even if the
|
|
| 568 | - demand signature of 'f' specifies that it is strict in its argument. We
|
|
| 569 | - considered fixing this this by adding a special case to the demand
|
|
| 570 | - analyser to address #16588. However, the special case seemed like a large
|
|
| 571 | - and expensive hammer to address a rare case and consequently we rather
|
|
| 572 | - opted to use a more minimal solution.
|
|
| 584 | + We don't have type-or-constraint polymorphism, so we simply have two
|
|
| 585 | + `inline` Ids, namely `noinlineId` and `noinlineConstraintId`:
|
|
| 586 | + |
|
| 587 | + noinline :: forall (r::RuntimeRep) (a::TYPE r). a -> a
|
|
| 588 | + noinlineConstraint :: forall (r::RuntimeRep) (a::CONSTRAINT r). a => a
|
|
| 589 | + |
|
| 590 | + Tiresome but simple.
|
|
| 573 | 591 | |
| 574 | 592 | Note [nospecId magic]
|
| 575 | 593 | ~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -32,10 +32,13 @@ module GHC.Builtin.WiredIn.Prim( |
| 32 | 32 | |
| 33 | 33 | alphaConstraintTyVar, alphaConstraintTy,
|
| 34 | 34 | |
| 35 | - openAlphaTyVar, openBetaTyVar, openGammaTyVar,
|
|
| 36 | - openAlphaTyVarSpec, openBetaTyVarSpec, openGammaTyVarSpec,
|
|
| 37 | - openAlphaTy, openBetaTy, openGammaTy,
|
|
| 35 | + -- Runtime-rep-polymorphic tyvars, of kind (TYPE rr)
|
|
| 36 | + rrPolyTyVar1, rrPolyTyVar2, rrPolyTyVar3,
|
|
| 37 | + rrPolyTy1, rrPolyTy2, rrPolyTy3,
|
|
| 38 | + rrPolyTyVarSpec1, rrPolyTyVarSpec2, rrPolyTyVarSpec3,
|
|
| 39 | + rrPolyConstraintVar1, rrPolyConstraintTy1,
|
|
| 38 | 40 | |
| 41 | + -- Levity-polymorphic tyvars
|
|
| 39 | 42 | levPolyAlphaTyVar, levPolyBetaTyVar,
|
| 40 | 43 | levPolyAlphaTyVarSpec, levPolyBetaTyVarSpec,
|
| 41 | 44 | levPolyAlphaTy, levPolyBetaTy,
|
| ... | ... | @@ -503,24 +506,29 @@ runtimeRep1Ty, runtimeRep2Ty, runtimeRep3Ty :: RuntimeRepType |
| 503 | 506 | runtimeRep1Ty = mkTyVarTy runtimeRep1TyVar
|
| 504 | 507 | runtimeRep2Ty = mkTyVarTy runtimeRep2TyVar
|
| 505 | 508 | runtimeRep3Ty = mkTyVarTy runtimeRep3TyVar
|
| 506 | -openAlphaTyVar, openBetaTyVar, openGammaTyVar :: TyVar
|
|
| 507 | --- alpha :: TYPE r1
|
|
| 508 | --- beta :: TYPE r2
|
|
| 509 | --- gamma :: TYPE r3
|
|
| 510 | -[openAlphaTyVar,openBetaTyVar,openGammaTyVar]
|
|
| 509 | + |
|
| 510 | +rrPolyTyVar1, rrPolyTyVar2, rrPolyTyVar3, rrPolyConstraintVar1 :: TyVar
|
|
| 511 | +-- rrPolyTyVar1 :: TYPE r1
|
|
| 512 | +-- rrPolyTyVar2 :: TYPE r2
|
|
| 513 | +-- rrPolyTyVar2 :: TYPE r3
|
|
| 514 | +-- rrPolyConstraintVar1 :: CONSTRAINT r1
|
|
| 515 | +-- All have distinct uniques
|
|
| 516 | +[ rrPolyTyVar1, rrPolyTyVar2, rrPolyTyVar3, rrPolyConstraintVar1 ]
|
|
| 511 | 517 | = mkTemplateTyVars [ mk_TYPE_app runtimeRep1Ty
|
| 512 | 518 | , mk_TYPE_app runtimeRep2Ty
|
| 513 | - , mk_TYPE_app runtimeRep3Ty]
|
|
| 514 | - |
|
| 515 | -openAlphaTyVarSpec, openBetaTyVarSpec, openGammaTyVarSpec :: TyVarBinder
|
|
| 516 | -openAlphaTyVarSpec = mkTyVarBinder Specified openAlphaTyVar
|
|
| 517 | -openBetaTyVarSpec = mkTyVarBinder Specified openBetaTyVar
|
|
| 518 | -openGammaTyVarSpec = mkTyVarBinder Specified openGammaTyVar
|
|
| 519 | - |
|
| 520 | -openAlphaTy, openBetaTy, openGammaTy :: Type
|
|
| 521 | -openAlphaTy = mkTyVarTy openAlphaTyVar
|
|
| 522 | -openBetaTy = mkTyVarTy openBetaTyVar
|
|
| 523 | -openGammaTy = mkTyVarTy openGammaTyVar
|
|
| 519 | + , mk_TYPE_app runtimeRep3Ty
|
|
| 520 | + , mk_CONSTRAINT_app runtimeRep1Ty ]
|
|
| 521 | + |
|
| 522 | +rrPolyTyVarSpec1, rrPolyTyVarSpec2, rrPolyTyVarSpec3 :: TyVarBinder
|
|
| 523 | +rrPolyTyVarSpec1 = mkTyVarBinder Specified rrPolyTyVar1
|
|
| 524 | +rrPolyTyVarSpec2 = mkTyVarBinder Specified rrPolyTyVar2
|
|
| 525 | +rrPolyTyVarSpec3 = mkTyVarBinder Specified rrPolyTyVar3
|
|
| 526 | + |
|
| 527 | +rrPolyTy1, rrPolyTy2, rrPolyTy3, rrPolyConstraintTy1 :: Type
|
|
| 528 | +rrPolyTy1 = mkTyVarTy rrPolyTyVar1
|
|
| 529 | +rrPolyTy2 = mkTyVarTy rrPolyTyVar2
|
|
| 530 | +rrPolyTy3 = mkTyVarTy rrPolyTyVar3
|
|
| 531 | +rrPolyConstraintTy1 = mkTyVarTy rrPolyConstraintVar1
|
|
| 524 | 532 | |
| 525 | 533 | levity1TyVar, levity2TyVar :: TyVar
|
| 526 | 534 | (levity2TyVar : levity1TyVar : _) -- NB: levity2TyVar before levity1TyVar
|
| ... | ... | @@ -60,8 +60,8 @@ import GHC.Types.Tickish |
| 60 | 60 | import GHC.Types.Var ( isTyCoVar )
|
| 61 | 61 | |
| 62 | 62 | import GHC.Builtin.WiredIn.Prim( realWorldStatePrimTy )
|
| 63 | -import GHC.Builtin.KnownKeys( runRWKey, seqHashKey, noinlineIdKey )
|
|
| 64 | -import GHC.Builtin.WiredIn.Ids( seqId )
|
|
| 63 | +import GHC.Builtin.KnownKeys( runRWKey, seqHashKey )
|
|
| 64 | +import GHC.Builtin.WiredIn.Ids( seqId, getNoinlineId, isNoinlineId )
|
|
| 65 | 65 | |
| 66 | 66 | import qualified GHC.Data.List.Infinite as Inf
|
| 67 | 67 | import GHC.Data.Maybe ( isNothing, orElse, mapMaybe )
|
| ... | ... | @@ -2369,8 +2369,8 @@ simplOutId env fun cont |
| 2369 | 2369 | call' = mkApps (Var fun) [mkTyArg rr', mkTyArg new_runrw_res_ty, arg']
|
| 2370 | 2370 | ; rebuild_go env call' outer_cont }
|
| 2371 | 2371 | |
| 2372 | -simplOutId env inline_fun cont
|
|
| 2373 | - | inline_fun `hasKey` noinlineIdKey
|
|
| 2372 | +simplOutId env noinline_fun cont
|
|
| 2373 | + | isNoinlineId noinline_fun
|
|
| 2374 | 2374 | , ApplyToTy { sc_cont = cont1 } <- cont
|
| 2375 | 2375 | , ApplyToTy { sc_cont = cont2 } <- cont1
|
| 2376 | 2376 | , ApplyToVal { sc_cont = cont3, sc_arg = the_call, sc_cast = arg_mco
|
| ... | ... | @@ -2386,10 +2386,12 @@ simplOutId env inline_fun cont |
| 2386 | 2386 | ; let call_env = updMode updModeForNoInline $
|
| 2387 | 2387 | arg_se `setInScopeFromE` env
|
| 2388 | 2388 | ; (floats1, call') <- simplExprF call_env inner_fun call_cont
|
| 2389 | - ; let new_call_ty = contHoleType rest_cont
|
|
| 2390 | - noinline_expr = Var inline_fun `App` Type (getRuntimeRep new_call_ty)
|
|
| 2391 | - `App` Type new_call_ty
|
|
| 2392 | - `App` mkCastMCo call' arg_mco
|
|
| 2389 | + ; let new_call_ty = contHoleType rest_cont
|
|
| 2390 | + (new_noinline_fun, rep) = getNoinlineId new_call_ty
|
|
| 2391 | + noinline_expr = Var new_noinline_fun
|
|
| 2392 | + `App` Type rep
|
|
| 2393 | + `App` Type new_call_ty
|
|
| 2394 | + `App` mkCastMCo call' arg_mco
|
|
| 2393 | 2395 | ; (floats2, res) <- rebuild env noinline_expr rest_cont
|
| 2394 | 2396 | ; return (floats2 `addFloats` floats1 , res) }
|
| 2395 | 2397 |
| ... | ... | @@ -114,7 +114,8 @@ type KindOrType = Type -- See Note [Arguments to type constructors] |
| 114 | 114 | -- | The key type representing kinds in the compiler.
|
| 115 | 115 | type Kind = Type
|
| 116 | 116 | |
| 117 | --- | Type synonym used for types of kind RuntimeRep.
|
|
| 117 | +-- | Type synonym used for Types of kind RuntimeRep.
|
|
| 118 | +-- E.g. The type IntRep :: RuntimeRep
|
|
| 118 | 119 | type RuntimeRepType = Type
|
| 119 | 120 | |
| 120 | 121 | -- | Type synonym used for types of kind Levity.
|
| ... | ... | @@ -2686,7 +2686,7 @@ typeKind ty@(ForAllTy {}) |
| 2686 | 2686 | |
| 2687 | 2687 | ---------------------------------------------
|
| 2688 | 2688 | |
| 2689 | -sORTKind_maybe :: Kind -> Maybe (TypeOrConstraint, Type)
|
|
| 2689 | +sORTKind_maybe :: Kind -> Maybe (TypeOrConstraint, RuntimeRepType)
|
|
| 2690 | 2690 | -- Sees if the argument is of form (TYPE rep) or (CONSTRAINT rep)
|
| 2691 | 2691 | -- and if so returns which, and the runtime rep
|
| 2692 | 2692 | --
|
| ... | ... | @@ -63,7 +63,7 @@ import GHC.Core.TyCo.Tidy |
| 63 | 63 | |
| 64 | 64 | import GHC.Builtin.WiredIn.Prim ( eqPrimTyCon, eqReprPrimTyCon )
|
| 65 | 65 | import GHC.Builtin.WiredIn.Types ( heqTyCon )
|
| 66 | -import GHC.Builtin.WiredIn.Ids ( noinlineIdName )
|
|
| 66 | +import GHC.Builtin.WiredIn.Ids ( getNoinlineId )
|
|
| 67 | 67 | |
| 68 | 68 | import GHC.Iface.Syntax
|
| 69 | 69 | import GHC.Data.FastString
|
| ... | ... | @@ -658,9 +658,9 @@ toIfaceVar :: Id -> IfaceExpr |
| 658 | 658 | toIfaceVar v
|
| 659 | 659 | | isBootUnfolding (idUnfolding v)
|
| 660 | 660 | = -- See Note [Inlining and hs-boot files]
|
| 661 | - IfaceExt noinlineIdName `IfaceApp`
|
|
| 662 | - IfaceType (toIfaceType rep) `IfaceApp`
|
|
| 663 | - IfaceType (toIfaceType ty) `IfaceApp`
|
|
| 661 | + IfaceExt (idName noinline_id) `IfaceApp`
|
|
| 662 | + IfaceType (toIfaceType rep) `IfaceApp`
|
|
| 663 | + IfaceType (toIfaceType ty) `IfaceApp`
|
|
| 664 | 664 | IfaceExt name -- Don't use mkIfaceApps, or infinite loop
|
| 665 | 665 | |
| 666 | 666 | | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType (idType v))
|
| ... | ... | @@ -671,7 +671,7 @@ toIfaceVar v |
| 671 | 671 | where
|
| 672 | 672 | name = idName v
|
| 673 | 673 | ty = idType v
|
| 674 | - rep = getRuntimeRep ty
|
|
| 674 | + (noinline_id, rep) = getNoinlineId ty
|
|
| 675 | 675 | |
| 676 | 676 | ---------------------
|
| 677 | 677 | toIfaceLFInfo :: Name -> LambdaFormInfo -> IfaceLFInfo
|
| ... | ... | @@ -750,7 +750,7 @@ But how do we arrange for this to happen? There are two ingredients: |
| 750 | 750 | 1. When we serialize out unfoldings to IfaceExprs (toIfaceVar),
|
| 751 | 751 | for every variable reference we see if we are referring to an
|
| 752 | 752 | 'Id' that came from an hs-boot file. If so, we add a `noinline`
|
| 753 | - to the reference. See Note [noinlineId magic]
|
|
| 753 | + to the reference. See Note [noinlineId magic] esp (NOI3)
|
|
| 754 | 754 | in GHC.Types.Id.Make
|
| 755 | 755 | |
| 756 | 756 | 2. But how do we know if a reference came from an hs-boot file
|
| ... | ... | @@ -28,7 +28,7 @@ import GHC.Builtin.PrimOps |
| 28 | 28 | import GHC.Builtin.PrimOps.Ids
|
| 29 | 29 | import GHC.Builtin.WiredIn.Types
|
| 30 | 30 | import GHC.Builtin.WiredIn.Prim
|
| 31 | -import GHC.Builtin.WiredIn.Ids ( realWorldPrimId )
|
|
| 31 | +import GHC.Builtin.WiredIn.Ids ( realWorldPrimId, isNoinlineId )
|
|
| 32 | 32 | |
| 33 | 33 | import GHC.Core.Utils
|
| 34 | 34 | import GHC.Core.Opt.Arity
|
| ... | ... | @@ -1274,7 +1274,7 @@ eliminateMagicCall f (AIApp Type{} : AIApp arg : args) |
| 1274 | 1274 | -- See Note [nospecId magic] in GHC.Types.Id.Make
|
| 1275 | 1275 | |
| 1276 | 1276 | eliminateMagicCall f (AIApp Type{} : AIApp Type{} : AIApp arg : args)
|
| 1277 | - | f `hasKey` noinlineIdKey = Just (arg,args)
|
|
| 1277 | + | isNoinlineId f = Just (arg,args)
|
|
| 1278 | 1278 | -- Replace (noinline a) with a
|
| 1279 | 1279 | -- See Note [noinlineId magic] in GHC.Types.Id.Make
|
| 1280 | 1280 |
| ... | ... | @@ -706,8 +706,10 @@ patchMagicDefn orig_pair@(orig_id, orig_rhs) |
| 706 | 706 | = do { magic_pair@(magic_id, _) <- mk_magic_pair orig_id orig_rhs
|
| 707 | 707 | |
| 708 | 708 | -- Patching should not change the Name or the type of the Id
|
| 709 | - ; massert (getUnique magic_id == getUnique orig_id)
|
|
| 710 | - ; massert (varType magic_id `eqType` varType orig_id)
|
|
| 709 | + ; massertPpr (getUnique magic_id == getUnique orig_id) (ppr orig_id)
|
|
| 710 | + ; massertPpr (varType magic_id `eqType` varType orig_id) $
|
|
| 711 | + vcat [ text "orig_id:" <+> ppr orig_id <+> dcolon <+> ppr (varType orig_id)
|
|
| 712 | + , text "magic_id:" <+> ppr magic_id <+> dcolon <+> ppr (varType magic_id) ]
|
|
| 711 | 713 | |
| 712 | 714 | ; return magic_pair }
|
| 713 | 715 | | otherwise
|
| ... | ... | @@ -752,7 +754,7 @@ mkUnsafeCoercePrimPair _old_id old_expr |
| 752 | 754 | ; let [unsafe_refl_data_con] = tyConDataCons unsafe_equality_tc
|
| 753 | 755 | |
| 754 | 756 | rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar
|
| 755 | - , openAlphaTyVar, openBetaTyVar
|
|
| 757 | + , rrPolyTyVar1, rrPolyTyVar2
|
|
| 756 | 758 | , x ] $
|
| 757 | 759 | mkSingleAltCase scrut1
|
| 758 | 760 | (mkWildValBinder ManyTy scrut1_ty)
|
| ... | ... | @@ -765,7 +767,7 @@ mkUnsafeCoercePrimPair _old_id old_expr |
| 765 | 767 | Var x `mkCast` x_co
|
| 766 | 768 | |
| 767 | 769 | [x, rr_cv, ab_cv] = mkTemplateLocals
|
| 768 | - [ openAlphaTy -- x :: a
|
|
| 770 | + [ rrPolyTy1 -- x :: a
|
|
| 769 | 771 | , rr_cv_ty -- rr_cv :: r1 ~# r2
|
| 770 | 772 | , ab_cv_ty -- ab_cv :: (alpha |> alpha_co ~# beta)
|
| 771 | 773 | ]
|
| ... | ... | @@ -783,15 +785,15 @@ mkUnsafeCoercePrimPair _old_id old_expr |
| 783 | 785 | runtimeRep1Ty
|
| 784 | 786 | runtimeRep2Ty
|
| 785 | 787 | (scrut2, scrut2_ty, ab_cv_ty) = unsafe_equality (mkTYPEapp runtimeRep2Ty)
|
| 786 | - (openAlphaTy `mkCastTy` alpha_co)
|
|
| 787 | - openBetaTy
|
|
| 788 | + (rrPolyTy1 `mkCastTy` alpha_co)
|
|
| 789 | + rrPolyTy2
|
|
| 788 | 790 | |
| 789 | 791 | -- alpha_co :: TYPE r1 ~# TYPE r2
|
| 790 | 792 | -- alpha_co = TYPE rr_cv
|
| 791 | 793 | alpha_co = mkTyConAppCo Nominal tYPETyCon [mkCoVarCo rr_cv]
|
| 792 | 794 | |
| 793 | 795 | -- x_co :: alpha ~R# beta
|
| 794 | - x_co = mkGReflMCo Representational openAlphaTy alpha_co `mkTransCo`
|
|
| 796 | + x_co = mkGReflMCo Representational rrPolyTy1 alpha_co `mkTransCo`
|
|
| 795 | 797 | mkSubCo (mkCoVarCo ab_cv)
|
| 796 | 798 | |
| 797 | 799 | |
| ... | ... | @@ -800,13 +802,13 @@ mkUnsafeCoercePrimPair _old_id old_expr |
| 800 | 802 | `setArityInfo` arity
|
| 801 | 803 | |
| 802 | 804 | ty = mkSpecForAllTys [ runtimeRep1TyVar, runtimeRep2TyVar
|
| 803 | - , openAlphaTyVar, openBetaTyVar ] $
|
|
| 804 | - mkVisFunTyMany openAlphaTy openBetaTy
|
|
| 805 | + , rrPolyTyVar1, rrPolyTyVar2 ] $
|
|
| 806 | + mkVisFunTyMany rrPolyTy1 rrPolyTy2
|
|
| 805 | 807 | |
| 806 | 808 | arity = 1
|
| 807 | 809 | |
| 808 | 810 | concs = mkRepPolyIdConcreteTyVars
|
| 809 | - [((mkTyVarTy openAlphaTyVar, mkArgPos 1 Top), runtimeRep1TyVar)]
|
|
| 811 | + [((rrPolyTy1, mkArgPos 1 Top), runtimeRep1TyVar)]
|
|
| 810 | 812 | unsafeCoercePrimName
|
| 811 | 813 | |
| 812 | 814 | id = mkExportedLocalId (RepPolyId concs) unsafeCoercePrimName ty `setIdInfo` info
|
| ... | ... | @@ -443,7 +443,7 @@ matchWithDict [cls_ty, mty] |
| 443 | 443 | , Just (cls, dict_dc) <- isUnaryClassTyCon_maybe dict_tc
|
| 444 | 444 | , [inst_meth_ty] <- dataConInstArgTys dict_dc dict_args
|
| 445 | 445 | = do { sv <- mkSysLocalM (fsLit "withDict_s") ManyTy mty
|
| 446 | - ; k <- mkSysLocalM (fsLit "withDict_k") ManyTy (mkInvisFunTy cls_ty openAlphaTy)
|
|
| 446 | + ; k <- mkSysLocalM (fsLit "withDict_k") ManyTy (mkInvisFunTy cls_ty rrPolyTy1)
|
|
| 447 | 447 | ; wd_cls <- tcLookupKnownKeyClass withDictClassKey
|
| 448 | 448 | |
| 449 | 449 | -- Given ev_expr : mty ~N# inst_meth_ty, construct the method of
|
| ... | ... | @@ -452,7 +452,7 @@ matchWithDict [cls_ty, mty] |
| 452 | 452 | -- \@(r :: RuntimeRep) @(a :: TYPE r) (sv :: mty) (k :: cls => a) ->
|
| 453 | 453 | -- k (MkC tys (sv |> sub co2))
|
| 454 | 454 | ; let evWithDict ev_expr
|
| 455 | - = mkCoreLams [ runtimeRep1TyVar, openAlphaTyVar, sv, k ] $
|
|
| 455 | + = mkCoreLams [ runtimeRep1TyVar, rrPolyTyVar1, sv, k ] $
|
|
| 456 | 456 | Var k `App` (evUnaryDictAppE cls dict_args meth_arg)
|
| 457 | 457 | where
|
| 458 | 458 | meth_arg = Var sv `mkCast` mkSubCo (evExprCoercion ev_expr)
|
| ... | ... | @@ -62,9 +62,14 @@ inline x = x |
| 62 | 62 | -- | The call @noinline f@ arranges that @f@ will not be inlined.
|
| 63 | 63 | -- It is removed during CorePrep so that its use imposes no overhead
|
| 64 | 64 | -- (besides the fact that it blocks inlining.)
|
| 65 | -noinline :: a -> a
|
|
| 66 | -{-# NOINLINE noinline #-} -- noinline is inlined manually in CorePrep
|
|
| 67 | -noinline x = x
|
|
| 65 | +noinline :: forall (r :: RuntimeRep) (a :: TYPE r).
|
|
| 66 | + a -> a
|
|
| 67 | +{-# NOINLINE noinline #-}
|
|
| 68 | +-- See Note [noinlineId magic] in GHC.Builtin.WiredIn.Ids
|
|
| 69 | +noinline = noinline -- Never called, eliminated in CorePrep
|
|
| 70 | + -- We can't conveniently call `error` here because
|
|
| 71 | + -- GHC.Internal.Err depends on GHC.Internal.Magic.noinline!
|
|
| 72 | + -- Hence this silly loop.
|
|
| 68 | 73 | |
| 69 | 74 | -- | The 'lazy' function restrains strictness analysis a little. The
|
| 70 | 75 | -- call @lazy e@ means the same as @e@, but 'lazy' has a magical
|
| ... | ... | @@ -28,7 +28,7 @@ import GHC.Builtin.PrimOps.Ids |
| 28 | 28 | ( primOpId )
|
| 29 | 29 | import GHC.Builtin.WiredIn.Prim
|
| 30 | 30 | ( runtimeRep1Ty, runtimeRep1TyVar
|
| 31 | - , openAlphaTy, openAlphaTyVar
|
|
| 31 | + , rrPolyTyVar1, rrPolyTy1
|
|
| 32 | 32 | )
|
| 33 | 33 | |
| 34 | 34 | import GHC.Core
|
| ... | ... | @@ -79,7 +79,7 @@ test_exprs = |
| 79 | 79 | [ Type liftedDataConTy
|
| 80 | 80 | , Type liftedRepTy
|
| 81 | 81 | , Type intTy
|
| 82 | - , Type $ mkVisFunTyMany openAlphaTy openAlphaTy
|
|
| 82 | + , Type $ mkVisFunTyMany rrPolyTy1 rrPolyTy1
|
|
| 83 | 83 | ]
|
| 84 | 84 | , ("raise# OK 2", ) $
|
| 85 | 85 | -- raise# @Lifted @r
|
| ... | ... | @@ -107,7 +107,7 @@ test_exprs = |
| 107 | 107 | |
| 108 | 108 | -- These will be considered in-scope by the Core Lint checks.
|
| 109 | 109 | in_scope :: [ Id ]
|
| 110 | -in_scope = [ runtimeRep1TyVar, openAlphaTyVar ]
|
|
| 110 | +in_scope = [ runtimeRep1TyVar, rrPolyTyVar1 ]
|
|
| 111 | 111 | |
| 112 | 112 | main :: IO ()
|
| 113 | 113 | main = do
|
| ... | ... | @@ -751,15 +751,16 @@ ppTyVar "a" = nonDepTyVarBinder "alphaTyVarSpec" |
| 751 | 751 | ppTyVar "b" = nonDepTyVarBinder "betaTyVarSpec"
|
| 752 | 752 | ppTyVar "c" = nonDepTyVarBinder "gammaTyVarSpec"
|
| 753 | 753 | ppTyVar "s" = nonDepTyVarBinder "deltaTyVarSpec"
|
| 754 | + |
|
| 754 | 755 | -- See Note [Levity and representation polymorphic primops] in primops.txt.pp
|
| 755 | 756 | ppTyVar "a_reppoly"
|
| 756 | 757 | = PrimOpTyVarBinder
|
| 757 | 758 | { inferredTyVarBinders = ["runtimeRep1TyVarInf"]
|
| 758 | - , primOpTyVarBinder = "openAlphaTyVarSpec" }
|
|
| 759 | + , primOpTyVarBinder = "rrPolyTyVarSpec1" }
|
|
| 759 | 760 | ppTyVar "b_reppoly"
|
| 760 | 761 | = PrimOpTyVarBinder
|
| 761 | 762 | { inferredTyVarBinders = ["runtimeRep2TyVarInf"]
|
| 762 | - , primOpTyVarBinder = "openBetaTyVarSpec" }
|
|
| 763 | + , primOpTyVarBinder = "rrPolyTyVarSpec2" }
|
|
| 763 | 764 | ppTyVar "a_levpoly"
|
| 764 | 765 | = PrimOpTyVarBinder
|
| 765 | 766 | { inferredTyVarBinders = ["levity1TyVarInf"]
|
| ... | ... | @@ -802,8 +803,8 @@ ppType (TyVar "b") = "betaTy" |
| 802 | 803 | ppType (TyVar "c") = "gammaTy"
|
| 803 | 804 | ppType (TyVar "s") = "deltaTy"
|
| 804 | 805 | -- See Note [Levity and representation polymorphic primops] in primops.txt.pp
|
| 805 | -ppType (TyVar "a_reppoly") = "openAlphaTy"
|
|
| 806 | -ppType (TyVar "b_reppoly") = "openBetaTy"
|
|
| 806 | +ppType (TyVar "a_reppoly") = "rrPolyTy1"
|
|
| 807 | +ppType (TyVar "b_reppoly") = "rrPolyTy2"
|
|
| 807 | 808 | ppType (TyVar "a_levpoly") = "levPolyAlphaTy"
|
| 808 | 809 | ppType (TyVar "b_levpoly") = "levPolyBetaTy"
|
| 809 | 810 |