Commit 9789b032 authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Implement a typing rule for saturated seq, and document it

Also add notes about unsafeCoerce

The general thread here is to reduce use of ArgKind after
the type checker; it is so fragile!
parent e867f423
......@@ -881,11 +881,11 @@ unsafeCoerceId
`setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [argAlphaTyVar,openBetaTyVar]
(mkFunTy argAlphaTy openBetaTy)
[x] = mkTemplateLocals [argAlphaTy]
rhs = mkLams [argAlphaTyVar,openBetaTyVar,x] $
Cast (Var x) (mkUnsafeCo argAlphaTy openBetaTy)
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
(mkFunTy openAlphaTy openBetaTy)
[x] = mkTemplateLocals [openAlphaTy]
rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
Cast (Var x) (mkUnsafeCo openAlphaTy openBetaTy)
nullAddrId :: Id
......@@ -906,10 +906,12 @@ seqId = pcMiscPrelId seqName ty info
`setSpecInfo` mkSpecInfo [seq_cast_rule]
ty = mkForAllTys [alphaTyVar,argBetaTyVar]
(mkFunTy alphaTy (mkFunTy argBetaTy argBetaTy))
[x,y] = mkTemplateLocals [alphaTy, argBetaTy]
rhs = mkLams [alphaTyVar,argBetaTyVar,x,y] (Case (Var x) x argBetaTy [(DEFAULT, [], Var y)])
ty = mkForAllTys [alphaTyVar,betaTyVar]
(mkFunTy alphaTy (mkFunTy betaTy betaTy))
-- NB argBetaTyVar; see Note [seqId magic]
[x,y] = mkTemplateLocals [alphaTy, betaTy]
rhs = mkLams [alphaTyVar,betaTyVar,x,y] (Case (Var x) x betaTy [(DEFAULT, [], Var y)])
-- See Note [Built-in RULES for seq]
seq_cast_rule = BuiltinRule { ru_name = fsLit "seq of cast"
......@@ -933,12 +935,29 @@ lazyId = pcMiscPrelId lazyIdName ty info
ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy alphaTy)
Note [Unsafe coerce magic]
We define a *primitive*
and then in the base library we define the ordinary function
Unsafe.Coerce.unsafeCoerce :: forall (a:*) (b:*). a -> b
unsafeCoerce x = unsafeCoerce# x
Notice that unsafeCoerce has a civilized (albeit still dangerous)
polymorphic type, whose type args have kind *. So you can't use it on
unboxed values (unsafeCoerce 3#).
In contrast unsafeCoerce# is even more dangerous because you *can* use
it on unboxed things, (unsafeCoerce# 3#) :: Int. Its type is
forall (a:OpenKind) (b:OpenKind). a -> b
Note [seqId magic]
'GHC.Prim.seq' is special in several ways.
a) Its second arg can have an unboxed type
x `seq` (v +# w)
Hence its second type variable has ArgKind
b) Its fixity is set in LoadIface.ghcPrimIface
......@@ -832,6 +832,10 @@ tcApp (L loc (HsVar fun)) args res_ty
, [arg] <- args
= tcTagToEnum loc fun arg res_ty
| fun `hasKey` seqIdKey
, [arg1,arg2] <- args
= tcSeq loc fun arg1 arg2 res_ty
tcApp fun args res_ty
= do { -- Type-check the function
; (fun1, fun_tau) <- tcInferFun fun
......@@ -1118,6 +1122,18 @@ constructors of F [Int] but here we have to do it explicitly.
It's all grotesquely complicated.
tcSeq :: SrcSpan -> Name -> LHsExpr Name -> LHsExpr Name
-> TcRhoType -> TcM (HsExpr TcId)
-- (seq e1 e2) :: res_ty
-- We need a special typing rule because res_ty can be unboxed
tcSeq loc fun_name arg1 arg2 res_ty
= do { fun <- tcLookupId fun_name
; (arg1', arg1_ty) <- tcInfer (tcMonoExpr arg1)
; arg2' <- tcMonoExpr arg2 res_ty
; let fun' = L loc (HsWrap ty_args (HsVar fun))
ty_args = WpTyApp res_ty <.> WpTyApp arg1_ty
; return (HsApp (L loc (HsApp fun' arg1')) arg2') }
tcTagToEnum :: SrcSpan -> Name -> LHsExpr Name -> TcRhoType -> TcM (HsExpr TcId)
-- tagToEnum# :: forall a. Int# -> a
-- See Note [tagToEnum#] Urgh!
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment