[GHC] #9858: Typeable instances should be kind-aware
GHC
ghc-devs at haskell.org
Thu Apr 16 04:40:05 UTC 2015
#9858: Typeable instances should be kind-aware
-------------------------------------+-------------------------------------
Reporter: dreixel | Owner:
Type: bug | Status: merge
Priority: highest | Milestone: 7.10.2
Component: Compiler | Version: 7.9
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: None/Unknown | Unknown/Multiple
Blocked By: | Test Case:
Related Tickets: | typecheck/should_fail/T9858a,
| should_run/T9858b
| Blocking:
| Differential Revisions: Phab:D652
-------------------------------------+-------------------------------------
Comment (by oerjan):
Let me elaborate on my previous comment, especially the first suggestion,
since my hunch is that it requires the smallest changes to implement to
get back constraint `Typeable`s:
* Instead of prohibiting constraint `Typeable`s, ''detect'' the specific
case of `Typeable (() :: Constraint)` and give it a different instance
from `Typeable (() :: *)`.
== Why is this not less secure than the current fix? ==
As shown in comment [comment:90], the current fix only effectively
prohibits `Typeable` constraints for ''nullary'' constraint constructors.
For other constraints, while ordinary users are greatly inconvenienced, an
attacker can instead get the instances for all the constructors used (only
the ''exact'' kind of `Constraint` is disallowed, not e.g. `* ->
Constraint`) and put them together with type application, whose `Typeable`
instance needs to be polymorphic and therefore cannot reasonably check for
`Constraint` kinds.
All nullary constructors ''other'' than `()` are either kind monomorphic
or have kind parameters to distinguish the `TypeRep`s, so they are useless
to an attacker.
== How is it better? ==
It allows `Typeable` for constraints, which some people think are useful.
My feeling is that constraints, especially used as type parameters,
shouldn't be considered impredicative except ''possibly'' if they contain
`=>`.
Prohibiting this case was the 3rd suggestion, but my hunch is that this is
a more complicated change, and might, if desired, be better done with an
overall overhaul disallowing `=>` more uniformly in the same contexts as
quantified types, including disallowing splitting `a => b` into a type
application.
== How does it still seem a bit awkward? ==
It still allows some types to have identical `TypeRep`s, like `(,) :: * ->
* -> *` and `(,) :: Constraint -> Constraint -> Constraint`. This is no
change from the current fix, though.
Fixing this entirely was the 2nd suggestion. It might perhaps be
implemented directly, although my hunch is that it requires more work,
because it needs checking for partial applications and thus more
complicated kinds. I assume Edward's suggestion automatically implies
this.
== How is it sufficient? ==
With either my suggestion or the currently implemented fix, although some
types still have identical `TypeRep`s, I believe they can never have
identical ''kinds'' as well, and all cast operations require the actual
kinds of the compared `Typeable`s to be equal.
'''Proposition''': If two types `t` and `u` have the property:
* `t` and `u` are distinct as Haskell types, but have the same `TypeRep`
under the pre-fix system, and ''either'' both have the same kind or one
has kind `*` and the other has kind `Constraint`;
then one of the following holds:
* They have two corresponding type arguments with the same property.
* They are, in some order, `() :: *` and `() :: Constraint`.
'''Proof''': If at least one of `t` and `u` does ''not'' have as its tycon
one of the kind-ambiguous types `(), (,), ..., (->), (=>)`, then to have
equal `TypeRep`s, their tycons and lists of kindreps must be identical,
and the types themselves and all their arguments must have corresponding
kinds. Thus to be different as types two of their corresponding arguments
must have the property.
If the tycons ''are'' kind-ambiguous then any arguments must have kind
either `*` or `Constraint`. With no arguments, with the ''exception'' of
`()`, the types must have different kinds that are not `*` or
`Constraint`, a contradiction. Otherwise, the kinds of the tycons are
determined by the kinds of the first arguments, and for `t` and `u` to be
distinct, there must be two corresponding arguments with the property.
----
To justify the possibility of the 3rd alternative suggestion as well, the
above proof can be adjusted to show that if the kinds of `t` and `u` are
''equal'', then types of the form `a -> c` and `b => c` must appear as
corresponding arguments at some step. This is because all the other
options preserve whether the kinds of the arguments are equal or
different.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9858#comment:92>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list