proposal: add 'unsafeCoerce'
Donald Bruce Stewart
dons at cse.unsw.edu.au
Mon Nov 20 00:51:29 EST 2006
dons:
> iavor.diatchki:
> > Hello,
> > I think that it is a really bad idea to make 'unsafeCoerce' a part of
> > the standard libraries. As far as I understand, 'unsafeCoerce' is
> > only "safe" if the programmer assumes something about the
> > representations of values (in particular, that values of different
> > types have the same representations). Haskell makes no such
> > guarantees so, by definition, any program that uses 'unsafeCoerce' is
> > using an implementation specific extension. I was trying ot think of
> > cases where 'unsafeCoerce' might be somewhat safe, and the main
> > example I came up with is when the coersion happens on a phantom type.
> > Are there other reasonably portable examples?
A quick grep in the core libraries, for insight:
FFI stuff:
./base/Data/Array/Base.hs:678:
nullStablePtr = StablePtr (unsafeCoerce# 0#)
./base/Data/Array/Base.hs:1522:
case unsafeCoerce# memcpy marr'# marr# n# s2# of { (# s3#, () #) ->
./base/Data/Array/Base.hs:1592:
case unsafeCoerce# memcpy marr# arr# n# s2# of { (# s3#, () #) ->
./base/Data/Array/Base.hs:1657:
return (STUArray l u (unsafeCoerce# marr#))
Equalities not expressible in the type system:
./base/Data/Dynamic.hs:124:
toDyn v = Dynamic (typeOf v) (unsafeCoerce v)
./base/Data/Dynamic.hs:135:
| typeOf def == t = unsafeCoerce v
./base/Data/Dynamic.hs:147:
case unsafeCoerce v of
./base/Data/Dynamic.hs:155:
Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))
./base/Data/Typeable.hs:452:
then Just $ unsafeCoerce x
./base/Data/Typeable.hs:460:
then Just $ unsafeCoerce x
./base/Data/Typeable.hs:470:
then Just $ unsafeCoerce x
./base/Data/Typeable.hs:480:
then Just $ unsafeCoerce x
I was actually surprised to see. That could be removed I'm pretty sure:
./base/Data/ByteString/Char8.hs:304:
go :: Addr# -> [Char] -> ST a ()
go _ [] = return ()
go p (C# c:cs) = writeByte p (unsafeCoerce# c) >> go (p `plusAddr#` 1#) cs
And some GHC things
./base/GHC/Handle.hs:1661:
puts s = do write_rawBuffer 1 (unsafeCoerce# (packCString# s)) 0 (fromIntegral (length s))
./base/GHC/ForeignPtr.hs:159:
(# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))
./base/GHC/ForeignPtr.hs:171:
(# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))
./base/GHC/ForeignPtr.hs:193:
(# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))
./base/GHC/ForeignPtr.hs:205:
(# s, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#))
./base/GHC/ForeignPtr.hs:318:
castForeignPtr f = unsafeCoerce# f
And some FFI binding stuff:
./ObjectIO/Graphics/UI/ObjectIO/Process/IOState.hs:139:
| ioStGetIOId ioSt == id = unsafeCoerce# (ps, ioSt)
./ObjectIO/Graphics/UI/ObjectIO/Window/Access.hs:578:
| identifyWIDS wid wids = Just (unsafeCoerce# ls)
So the uses fall into 2 categories:
* FFI binding and raw pointer/foreign data manipulation
* type equalities known, but not expressible statically
Now, can we say something portable about these uses?
-- Don
More information about the Libraries
mailing list