[commit: base] master: Update base for new Safe Haskell design (447448a)

Simon Marlow marlowsd at gmail.com
Mon Oct 31 15:21:25 CET 2011


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<duncan.coutts at googlemail.com>   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







More information about the Cvs-libraries mailing list