[GHC] #12928: Too easy to trigger CUSK condition using TH
GHC
ghc-devs at haskell.org
Mon Dec 5 19:48:41 UTC 2016
#12928: Too easy to trigger CUSK condition using TH
-------------------------------------+-------------------------------------
Reporter: int-index | Owner:
Type: feature | Status: new
request |
Priority: high | Milestone:
Component: Compiler | Version: 8.0.1
(Type checker) |
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: GHC rejects
Unknown/Multiple | valid program
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
While trying to make `singletons` class promotion work with kind-
polymorphic type variables, I've encountered a problem regarding CUSKs.
Consider this class:
{{{
$(promoteOnly [d|
class Cls a where
fff :: Proxy a -> ()
|])
}}}
The generated TH (slightly simplified by hand) looks like this:
{{{
type FffSym1 (t_alvm :: Proxy a1627472612) = Fff t_alvm
data FffSym0 (l_alvn :: TyFun (Proxy a1627472612) ())
type instance Apply FffSym0 l_alvn = FffSym1 l_alvn
class PCls a_alve where
type Fff (arg_alvl :: Proxy a_alve) :: ()
}}}
However, it fails to compile with the following error:
{{{
cusk.hs:25:1: error:
You have written a *complete user-suppled kind signature*,
but the following variable is undetermined: k0 :: *
Perhaps add a kind signature.
Inferred kinds of user-written variables:
a1627472612 :: k0
l_alvn :: TyFun (Proxy a1627472612) ()
}}}
As suggested by the error message, we need to specify the kind in its
entirety (write a proper CUSK). So to sidestep the issue, we can write
{{{
data FffSym0 (l_alvn :: TyFun (Proxy (a1627472612 :: k)) ())
}}}
and it'll work. However, this means that the TH code generator should
perform some guesswork to modify kind annotations. It sounds like a
minefield — too much can go wrong, so it'd be great to avoid doing so.
Looking at the module `TcHsType` in the GHC sources, I see that the error
is reported by the `kcHsTyVarBndrs` function:
{{{
-- If there are any meta-tvs left, the user has
-- lied about having a CUSK. Error.
; let (meta_tvs, good_tvs) = partition isMetaTyVar qkvs
; when (not (null meta_tvs)) $
report_non_cusk_tvs (qkvs ++ tc_tvs)
}}}
However, I don't see why we can't generalize over `meta_tvs` instead of
reporting a failure. I asked on IRC #ghc and ezyang suggested that it
should be sound.
Below I attach a self-contained example that demonstrates the issue and
has no dependencies except `base`.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12928>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list