Generalized Newtype Deriving not allowed in Safe Haskell
Richard Eisenberg
eir at cis.upenn.edu
Fri Apr 10 12:07:05 UTC 2015
Here's an idea: For a module to be Safe, then for each exported datatype, one of the following must hold:
1) The datatype comes with a role annotation.
2) The module exports all of the datatype's constructors.
3) If the datatype is defined in a place other than the current module, the current module exports no fewer data constructors than are exported in the datatype's defining module.
Why?
1) The role annotation, even if it has no effect, shows that the programmer has considered roles. Any mistake here is clearly the programmer's fault.
2) This datatype is clearly meant not to be abstract. `Coercible` then gives clients no more power than they already have.
3) This is subtler. It is a common idiom to export a datatype's constructors from a package-internal module, but then never to export the constructors beyond the package. If such a datatype has a role annotation (in its defining module, of course), then we're fine, even if it is exported abstractly later. However, suppose we are abstractly re-exporting a datatype that exports its constructors from its defining module. If there is no role annotation on the datatype, we're in trouble and should fail. BUT, if the datatype were exported abstractly in its defining module, then we don't need to fail on re-export, because nothing has changed.
Actually, we could simplify the conditions. Change (2) to:
2') The module exports all of the datatype's visible constructors.
I think explaining in terms of separate rules (2) and (3) is a little clearer, because the re-export case is slightly subtle, and this subtlety can be lost in (2').
This proposal would require tracking (in interface files, too) whether or not a datatype comes with a role annotation. This isn't hard, though. It might even help in pretty-printing.
An alternative would be to have a way of setting roles differently on export than internally. I don't think this breaks the type system, but it's yet another thing to specify and support. And we'd have to consider the possibility that some module will import a datatype from multiple re-exporting modules, each with different ascribed role annotations. Is this an error? Does GHC take some sort of least upper bound? I prefer not to go here, but there's nothing terribly wrong with this approach.
Richard
On Apr 10, 2015, at 9:37 AM, David Terei <dave.terei at gmail.com> wrote:
> I'll prepare a patch for the userguide soon.
>
> As for something better, yes I think we can and should. It's on my
> todo list :) Basically, the new-GND design has all the mechanisms to
> be safe, but sadly the defaults are rather worrying. Without explicit
> annotations from the user, module abstractions are broken. This is why
> we left GND out of Safe Haskell for the moment as it is a subtle and
> easy mistake to make.
>
> If the module contained explicit role annotations then it could be
> allowed. The discussion in
> https://ghc.haskell.org/trac/ghc/ticket/8827 has other solutions that
> I prefer, such as only exporting the Coerce instance if all the
> constructors are exported, it seems that the ship sailed on these
> bigger changes sadly.
>
> Cheers,
> David
>
> On 9 April 2015 at 00:56, Simon Peyton Jones <simonpj at microsoft.com> wrote:
>> There is a long discussion on https://ghc.haskell.org/trac/ghc/ticket/8827
>> about whether the new Coercible story makes GND ok for Safe Haskell. At a
>> type-soundness level, definitely yes. But there are other less-clear-cut
>> issues like “breaking abstractions” to consider. The decision on the ticket
>> (comment:36) seems to be: GND stays out of Safe Haskell for now, but there
>> is room for a better proposal.
>>
>>
>>
>> I don’t have an opinion myself. David Terei and David Mazieres are in the
>> driving seat, but I’m sure they’ll be responsive to user input.
>>
>>
>>
>> However, I think the user manual may not have kept up with #8827. The
>> sentence “GeneralizedNewtypeDeriving — It can be used to violate constructor
>> access control, by allowing untrusted code to manipulate protected data
>> types in ways the data type author did not intend, breaking invariants they
>> have established.” vanished from the 7.8 user manual (links below). Maybe
>> it should be restored.
>>
>>
>>
>> Safe Haskell aficionados, would you like to offer a patch for the manual?
>> And maybe also a less drastic remedy than omitting GND altogether?
>>
>>
>>
>> Simon
>>
>>
>>
>> From: Omari Norman [mailto:omari at smileystation.com]
>> Sent: 09 April 2015 02:44
>> To: haskell Cafe
>> Subject: Generalized Newtype Deriving not allowed in Safe Haskell
>>
>>
>>
>> When compiling code with Generalized Newtype Deriving and the -fwarn-unsafe
>> flag, I get
>>
>>
>>
>> -XGeneralizedNewtypeDeriving is not allowed in Safe Haskell
>>
>>
>>
>> This happens both in GHC 7.8 and GHC 7.10.
>>
>>
>>
>> I thought I remembered reading somewhere that GNTD is now part of the safe
>> language? The GHC manual used to state that GNTD is not allowed in Safe
>> Haskell:
>>
>>
>>
>> https://downloads.haskell.org/~ghc/7.6.3/docs/html/users_guide/safe-haskell.html#safe-language
>>
>>
>>
>> But this language on GNTD not being part of the safe language was removed in
>> the 7.8 manual:
>>
>>
>>
>> https://downloads.haskell.org/~ghc/7.8.2/docs/html/users_guide/safe-haskell.html#safe-language
>>
>>
>>
>> The GHC release notes don't say anything about this one way or the other.
>> Thoughts?
>>
>>
>> _______________________________________________
>> ghc-devs mailing list
>> ghc-devs at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>>
> _______________________________________________
> ghc-devs mailing list
> ghc-devs at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>
More information about the ghc-devs
mailing list