clarify that unsafeCoerce# :: Float# -> Int# is not safe (see #2209)
[ghc-hetmet.git] / compiler / prelude / primops.txt.pp
index 335a717..471cba1 100644 (file)
@@ -618,6 +618,13 @@ primop   DoubleDecodeOp   "decodeDouble#" GenPrimOp
     represent an {\tt Integer\#} holding the mantissa.}
    with out_of_line = True
 
+primop   DoubleDecode_2IntOp   "decodeDouble_2Int#" GenPrimOp    
+   Double# -> (# Int#, Int#, Int# #)
+   {Convert to arbitrary-precision integer.
+    First {\tt Int\#} in result is the high 32 bits of the mantissa, and the
+    second is the low 32. The third is the exponent.}
+   with out_of_line = True
+
 ------------------------------------------------------------------------
 section "Float#" 
        {Operations on single-precision (32-bit) floating-point numbers.}
@@ -724,6 +731,12 @@ primop   FloatDecodeOp   "decodeFloat#" GenPrimOp
     represent an {\tt Integer\#} holding the mantissa.}
    with out_of_line = True
 
+primop   FloatDecode_IntOp   "decodeFloat_Int#" GenPrimOp
+   Float# -> (# Int#, Int# #)
+   {Convert to arbitrary-precision integer.
+    First {\tt Int\#} in result is the mantissa; second is the exponent.}
+   with out_of_line = True
+
 ------------------------------------------------------------------------
 section "Arrays"
        {Operations on {\tt Array\#}.}
@@ -1240,7 +1253,7 @@ primop  CatchOp "catch#" GenPrimOp
 primop  RaiseOp "raise#" GenPrimOp
    a -> b
    with
-   strictness  = { \ arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) }
+   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) }
       -- NB: result is bottom
    out_of_line = True
 
@@ -1660,7 +1673,7 @@ section "Tag to enum stuff"
 primop  DataToTagOp "dataToTag#" GenPrimOp
    a -> Int#
    with
-   strictness  = { \ arity -> mkStrictSig (mkTopDmdType [seqDmd] TopRes) }
+   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [seqDmd] TopRes) }
        -- dataToTag# must have an evaluated argument
 
 primop  TagToEnumOp "tagToEnum#" GenPrimOp     
@@ -1788,6 +1801,7 @@ pseudoop   "unsafeCoerce#"
          * Casting {\tt Any} back to the real type
 
          * Casting an unboxed type to another unboxed type of the same size
+           (but not coercions between floating-point and integral types)
 
          * Casting between two types that have the same runtime representation.  One case is when
            the two types differ only in "phantom" type parameters, for example
@@ -1795,7 +1809,14 @@ pseudoop   "unsafeCoerce#"
            known to be empty.  Also, a {\tt newtype} of a type {\tt T} has the same representation
            at runtime as {\tt T}.
 
-        Other uses of {\tt unsafeCoerce\#} are undefined.
+        Other uses of {\tt unsafeCoerce\#} are undefined.  In particular, you should not use
+       {\tt unsafeCoerce\#} to cast a T to an algebraic data type D, unless T is also
+       an algebraic data type.  For example, do not cast {\tt Int->Int} to {\tt Bool}, even if
+        you later cast that {\tt Bool} back to {\tt Int->Int} before applying it.  The reasons
+        have to do with GHC's internal representation details (for the congnoscenti, data values
+       can be entered but function closures cannot).  If you want a safe type to cast things
+       to, use {\tt Any}, which is not an algebraic data type.
+       
         }
 
 -- NB. It is tempting to think that casting a value to a type that it doesn't have is safe