Skip to content

mkWeak# has a very dangerous type

The mkWeak# primop has a type looking like this:

primop  MkWeakOp "mkWeak#" GenPrimOp
   o -> b -> c -> State# RealWorld -> (# State# RealWorld, Weak# b #)

But the third argument is allowed to be a null pointer (indicating no finaliser). That is why we see this code in GHC.TopHandler:

mkWeakThreadId :: ThreadId -> IO (Weak ThreadId)
mkWeakThreadId t@(ThreadId t#) = IO $ \s ->
   case mkWeak# t# t (unsafeCoerce# 0#) s of 
      (# s1, w #) -> (# s1, Weak w #)

But coercing a non-pointer to a pointer is dangerous. Very dangerous. Could crash the garbage collector. This is Not Right.

I found this when tidying up Core Lint. For now I have commented out the extra test, but it should be there!

lintCoercion (UnsafeCo ty1 ty2)
  = do { k1 <- lintType ty1
       ; _k2 <- lintType ty2
--       ; unless (k1 `eqKind` k2) $ 
--         failWithL (hang (ptext (sLit "Unsafe coercion changes kind"))
--                       2 (ppr co))
       ; return (k1, ty1, ty2) }

}

Trac metadata
Trac field Value
Version 7.4.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information