
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
On Mon, Oct 7, 2013 at 10:22 AM, Edward Kmett
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!