On 28/10/2011 13:21, Duncan Coutts wrote:
On Thu, 2011-10-27 at 09:12 +0100, Simon Marlow wrote:
On 26/10/2011 21:45, David Terei wrote:
Hi Duncan,
On 26 October 2011 06:05, Duncan Coutts<[email protected]> wrote:
I don't understand this. Is it required that we mark Data.Trace as
unsafe? Why is it not just left unmarked?
My previous understanding was that Unsafe was for modules that don't
break the language but rather break the encapsulation of abatract
datatypes, ie for Blah.Internals modules.
Data.Trace and indeed System.IO.Unsafe are not like this. They are
simply not -XSafe because they use unsafePerformIO or ghc primitives.
Yes and no. We infer safety now. So 'default' is hard to define but if
anything the default is actually more towards safe. The inference
tracks if a module imports any unsafe modules and if so marks it as
unsafe.
Which Debug.Trace does, it imports System.IO.Unsafe. In turn
System.IO.Unsafe can be infered to be unsafe because it imports GHC.IO.
The chain continues via GHC.Base --> GHC.Types (which defines the IO
datatype) --> GHC.Prim which defines State#, RealWorld etc.
We've never built into the Safe Haskell implementation any
specific knowledge of things like unsafePerformIO and GHC.*
primitives. Instead we handle these with the trust tracking mechanism.
So we do need to mark some of the base / root modules as Unsafe so
that this propagates through the rest of the module system.
If we marked no modules at all as Unsafe (including the GHC.* ones)
then you'd have a lot of modules being inferred safe when they aren't.
I thought that making GHC.Prim Unsafe would do everything for us? As a
result virtually everything becomes Unsafe, and we have to use explicit
Trustworthy pragmas to introduce safety.
Right.
For a moment I was thinking that the module that defines the IO type has
to be marked UNSAFE explicitly, because e.g. unsafeDupablePerformIO does
not use any ghc primitives:
lazy (case m realWorld# of (# _, r #) -> r)
Well, ok, it uses lazy, but that primitive isn't actually unsafe. It's
access to the IO constructor that lets the demons out.
But of course the definition of the IO type uses things from GHC.Prim,
so again we're ok.
Actually, I think realWorld# is the real demon here. You can't perform
any side effects at all without realWorld#.
Most of GHC.Prim is safe - even the side-effecting primops, but
realWorld# needs to be kept in jail with strictly limited visiting rights.
If Data.Trace were not automatically inferred as Unsafe we'd be in big
trouble. I agree with Duncan - marking it as Unsafe feels wrong (like
it could be hiding a bug). Perhaps we want
{-# LANGUAGE VerifyUnsafe #-}
It's not really a language feature anymore. We just want an assertion.
It could be some other pragma. Or just a test in the testsuite that the
inferred safety of all the modules in base is what we expect them to be.
A pragma assertion would have the advantage that other packages could
use it easily too.
Right, I think there was already a suggestion that we should have
-Wunsafe (warn if the module is not inferred to be Safe), we should also
have -Wsafe. These could be used with -Werror of course.
Cheers,
Simon
_______________________________________________
Cvs-libraries mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-libraries