diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-11-07 17:24:47 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-11-19 11:53:55 -0500 |
commit | 08d595c026f0774c51d85cbd790518055970ff2d (patch) | |
tree | 706d776534998f69ed8cb62e3befa471bf4fdfdd /compiler/basicTypes | |
parent | a8adb5b4d782b6166160a80adbf6c59452dc964d (diff) | |
download | haskell-08d595c026f0774c51d85cbd790518055970ff2d.tar.gz |
Give seq a more precise type and remove magic
`GHC.Prim.seq` previously had the rather plain type:
seq :: forall a b. a -> b -> b
However, it also had a special typing rule to applications
where `b` is not of kind `Type`.
Issue #17440 noted that levity polymorphism allows us to rather give
it the more precise type:
seq :: forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b
This allows us to remove the special typing rule that we previously
required to allow applications on unlifted arguments. T9404 contains a
non-Type application of `seq` which should verify that this works as
expected.
Closes #17440.
Diffstat (limited to 'compiler/basicTypes')
-rw-r--r-- | compiler/basicTypes/MkId.hs | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/compiler/basicTypes/MkId.hs b/compiler/basicTypes/MkId.hs index d9d23b1235..593f9ac3a9 100644 --- a/compiler/basicTypes/MkId.hs +++ b/compiler/basicTypes/MkId.hs @@ -1392,7 +1392,6 @@ seqId = pcMiscPrelId seqName ty info where info = noCafIdInfo `setInlinePragInfo` inline_prag `setUnfoldingInfo` mkCompulsoryUnfolding rhs - `setNeverLevPoly` ty inline_prag = alwaysInlinePragma `setInlinePragmaActivation` ActiveAfter @@ -1402,11 +1401,15 @@ seqId = pcMiscPrelId seqName ty info -- LHS of rules. That way we can have rules for 'seq'; -- see Note [seqId magic] - ty = mkSpecForAllTys [alphaTyVar,betaTyVar] - (mkVisFunTy alphaTy (mkVisFunTy betaTy betaTy)) + -- seq :: forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b + ty = + mkInvForAllTy runtimeRep2TyVar + $ mkSpecForAllTys [alphaTyVar, openBetaTyVar] + $ mkVisFunTy alphaTy (mkVisFunTy openBetaTy openBetaTy) - [x,y] = mkTemplateLocals [alphaTy, betaTy] - rhs = mkLams [alphaTyVar,betaTyVar,x,y] (Case (Var x) x betaTy [(DEFAULT, [], Var y)]) + [x,y] = mkTemplateLocals [alphaTy, openBetaTy] + rhs = mkLams ([runtimeRep2TyVar, alphaTyVar, openBetaTyVar, x, y]) $ + Case (Var x) x openBetaTy [(DEFAULT, [], Var y)] ------------------------------------------------ lazyId :: Id -- See Note [lazyId magic] @@ -1492,19 +1495,20 @@ Note [seqId magic] ~~~~~~~~~~~~~~~~~~ 'GHC.Prim.seq' is special in several ways. -a) In source Haskell its second arg can have an unboxed type - x `seq` (v +# w) - But see Note [Typing rule for seq] in TcExpr, which - explains why we give seq itself an ordinary type - seq :: forall a b. a -> b -> b - and treat it as a language construct from a typing point of view. +a) Its fixity is set in LoadIface.ghcPrimIface -b) Its fixity is set in LoadIface.ghcPrimIface - -c) It has quite a bit of desugaring magic. +b) It has quite a bit of desugaring magic. See DsUtils.hs Note [Desugaring seq (1)] and (2) and (3) -d) There is some special rule handing: Note [User-defined RULES for seq] +c) There is some special rule handing: Note [User-defined RULES for seq] + +Historical note: + In TcExpr we used to need a special typing rule for 'seq', to handle calls + whose second argument had an unboxed type, e.g. x `seq` 3# + + However, with levity polymorphism we can now give seq the type seq :: + forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b which handles this + case without special treatment in the typechecker. Note [User-defined RULES for seq] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1530,13 +1534,16 @@ If we wrote RULE "f/seq" forall n e. seq (f n) e = seq n e with rule arity 2, then two bad things would happen: - - The magical desugaring done in Note [seqId magic] item (c) + - The magical desugaring done in Note [seqId magic] item (b) for saturated application of 'seq' would turn the LHS into a case expression! - The code in Simplify.rebuildCase would need to actually supply the value argument, which turns out to be awkward. +See also: Note [User-defined RULES for seq] in Simplify. + + Note [lazyId magic] ~~~~~~~~~~~~~~~~~~~ lazy :: forall a?. a? -> a? (i.e. works for unboxed types too) |