Proposal: GHC.Generics marked UNSAFE for SafeHaskell

Edward Kmett ekmett
Mon Oct 7 18:01:51 UTC 2013


If I understand correctly, then all of the code in question should be in

compiler/typecheck/TcInstDcls.lhs

There are two code paths that would need changing around line 418:

       ; when (safeLanguageOn dflags) $
             mapM_ (\x -> when (typInstCheck x)
                               (addErrAt (getSrcSpan $ iSpec x) typInstErr))
                   local_infos

       ; when (safeInferOn dflags) $
             mapM_ (\x -> when (typInstCheck x) recordUnsafeInfer)
local_infos

The first is when the Safe pragma is present, the second is when we're
merely inferring safety.

You'd need to figure out how you wanted to refactor the helper
functions splitTypeable,
typInstCheck, typInstErr, and instMsg in the where clause immediately
below, or if you just wanted to duplicate the  Typeable logic.

-Edward



On Mon, Oct 7, 2013 at 1:33 PM, Ryan Newton <rrnewton at gmail.com> wrote:

> Thanks Edward!   That provides a real example of someone who uses both
> SafeHaskell and GHC.Generics in their libraries!  I'm glad to know such a
> person exists but that you don't depend on handwritten Generic instances.
>  (I'm also glad to hear that you care about SafeHaskell in the first place!)
>    I totally agree that #ifdef'ing on GHC version is a pain, and all that
> code would need to conditionally import GHC.Generics or GHC.Generics.Safe
> to retain -XSafe status.
>
> I'm perfectly happy with the GHC-internal fix if someone can point me to
> how to do it / where it should go.  I guess I'll start by greping for
> Typeable in the compiler.  Is this something you can do trivially Edward?
>  (Or others?)
>
> Just for reference here is a small patch to Base representing my
> library-based way of making the change discussed in this thread:
>
>
> https://github.com/rrnewton/packages-base/commit/23f8f464a0b46ca17c655c4144f7643c4bc6ea61
>
> Again, my use-case (closed/safe Eq & Ord instances) is a few steps removed
> from this Generics business and I don't feel strongly about how it gets
> done.  But having *SOME* way of doing it will be a massive boon to my lab's
> particular effort at maximizing the abilities of guaranteed-Safe
> deterministic parallelism in Haskell.  Further, I think anyone else who
> tries to do something in SafeHaskell that depends on guaranteeing a
> closed/controlled set of instances (SafeEq, SafeOrd but also others) based
> on GHC.Generics will *also* find this change useful.
>
> Best,
>   -Ryan
>
>
>
> On Mon, Oct 7, 2013 at 12:44 PM, Edward Kmett <ekmett at gmail.com> wrote:
>
>> I'd much rather have code that can compile as Safe rather than
>> Trustworthy. Trustworthy code is a pain to annotate the safety of
>> correctly.
>>
>> A one line change to GHC to ensure the safety of GHC.Generics and to
>> maximize the number of operations you can use safely seems entirely
>> reasonable.
>>
>> Otherwise I have to mark perfectly Safe-by-construction code Trustworthy,
>> enlarging the trusted code base considerably. Using properly constructed
>> Generic instances is perfectly safe.
>>
>> That library level fix has knock-on effects across the entire ecosystem
>> for anyone who cares about SafeHaskell. I tend to instantiate GHC.Generics
>> for any type in most of my packages. A quick grep finds 209 modules broken
>> in just the projects I have open in my working directory. That is a mixture
>> of public and private repos. The majority of which are public. So, I first
>> have to change a couple hundred import statements... conditionally on
>> compiler version, since I maintain wide support windows. This fix would
>> literally break SafeHaskell for me silently across almost everything I have
>> written, forcing me to run through tons of packages trying to figure out
>> what I have to change to get it back. I've done this song and dance before
>> trying to get lambdabot to build, since it uses lens these days. If I don't
>> get every one of them right lens builds as unsafe. There isn't a good
>> debugging process for this, as the only real way I have to know it worked
>> is to go through each one and make sure I didn't compromise safe haskell by
>> looking at the resulting haddocks for each case.
>>
>> The code that *uses* GHC.Generics uses their internals and is safe by
>> construction. It is only the instance construction that is unsafe, so lets
>> mark it as such.
>>
>> -Edward
>>
>>
>> On Mon, Oct 7, 2013 at 11:11 AM, Ryan Newton <rrnewton at gmail.com> wrote:
>>
>>> On Mon, Oct 7, 2013 at 10:22 AM, Edward Kmett <ekmett at gmail.com> wrote:
>>>
>>>> Am I correct in understanding your issue arises from manually rolled
>>>> instances of Generic, not from Generic itself?
>>>>
>>>
>>> Exactly.
>>>
>>>
>>>> Wouldn't then perhaps the better fix be to resurrect the old rule for
>>>> derived Typeable instances and apply it to Generic and Generic1 instead?
>>>>
>>> The new rule would be that if you hand-implemented Generic or Generic1
>>>> in your module it isn't Safe.
>>>>
>>>
>>> Ah... so you're proposing adding an extra rule to the GHC compiler
>>> itself?
>>>
>>> Isn't it simpler to do it just with a library-level fix?  I.e. my
>>> proposal is that GHC.Generics is marked as Unsafe.  And then if you really
>>> want you can mark your module as TrustWorthy even with manual instances.
>>>  (And then, yes, we'd need a GHC.Generics.Safe to pull the Generic symbol
>>> itself from when we just want to derive it.)
>>>
>>> That would make it so that derived Generic, Generic1 would be considered
>>>> Safe, and you wouldn't break literally every user of the library who care
>>>> about Safe Haskell.
>>>>
>>>
>>> Isn't that also accomplished just by "import GHC.Generic.Safe
>>> (Generic)"?  And the handful of hypothetical people that are using this
>>> right now can make that one-line fix.  I will *personally* make that fix
>>> for all those people if they would come forward and share the link to their
>>> code ;-).
>>>
>>> As it stands the things are damn-near impossible to get right
>>>> instantiating them by hand anyways, so I expect this would affect only 1 or
>>>> 2 users rather than all of them!
>>>>
>>>
>>> Exactly!
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20131007/229475aa/attachment-0001.html>




More information about the Libraries mailing list