[commit: ghc] master: Implement a typing rule for saturated seq, and document it (9789b03)

Simon Peyton Jones simonpj at microsoft.com
Fri Feb 17 15:03:49 CET 2012


Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/9789b032e9ce7a5030d534847ec94e5398b38def

>---------------------------------------------------------------

commit 9789b032e9ce7a5030d534847ec94e5398b38def
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Fri Feb 17 13:57:47 2012 +0000

    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!

>---------------------------------------------------------------

 compiler/basicTypes/MkId.lhs  |   37 ++++++++++++++++++++++++++++---------
 compiler/typecheck/TcExpr.lhs |   16 ++++++++++++++++
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/compiler/basicTypes/MkId.lhs b/compiler/basicTypes/MkId.lhs
index 60f4cf1..4671b39 100644
--- a/compiler/basicTypes/MkId.lhs
+++ b/compiler/basicTypes/MkId.lhs
@@ -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)
 \end{code}
 
+Note [Unsafe coerce magic]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+We define a *primitive*
+   GHC.Prim.unsafeCoerce#
+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
 
diff --git a/compiler/typecheck/TcExpr.lhs b/compiler/typecheck/TcExpr.lhs
index fb6ca80..488e654 100644
--- a/compiler/typecheck/TcExpr.lhs
+++ b/compiler/typecheck/TcExpr.lhs
@@ -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.
 
 \begin{code}
+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!





More information about the Cvs-ghc mailing list