#15870 closed bug (fixed)

No skolem info panic

Reported by: sheaf Owned by:
Priority: highest Milestone: 8.6.3
Component: Compiler (Type checker) Version: 8.6.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Compile-time crash or panic Test Case: indexed-types/should_fail/T15870
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


I've been toying with some type-level lenses and running into some issues with kind unification, when I ran into a panic:

bug.hs:30:34: error:ghc.exe: panic! (the 'impossible' happened)
  (GHC version 8.6.2 for x86_64-unknown-mingw32):
        No skolem info:
  Call stack:
      CallStack (from HasCallStack):
        callStackDoc, called at compiler\utils\Outputable.hs:1160:37 in ghc:Outputable
        pprPanic, called at compiler\\typecheck\\TcErrors.hs:2891:5 in ghc:TcErrors

Here's a boiled down version (with a bit of extraneous code left in for context, as it's so short):

{-# LANGUAGE DataKinds              #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE GADTs                  #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE PolyKinds              #-}
{-# LANGUAGE ScopedTypeVariables    #-}
{-# LANGUAGE TypeFamilies           #-}
{-# LANGUAGE TypeOperators          #-}

data Optic a where
  --Index :: Nat    -> Optic a
  --Name  :: Symbol -> Optic a
  (:.:) :: Optic a -> Optic b -> Optic a -- composition

class Gettable a (optic :: Optic a) where
  type Get a (optic :: Optic a)

some basic instances, e.g.
instance Gettable (a,b) (Index 0) where
  type Get (a,b) (Index 0) = a

instance forall a b (g1 :: Optic a) (g2 :: Optic b).
        ( Gettable a g1
        , b ~ Get a g1
        , Gettable b g2
        ) => Gettable a (g1 :.: g2) where
  type Get a (g1 :.: g2) = Get a g2

The program I am actually trying to write has the instance declaration changed to

instance forall a b (g1 :: Optic a) (g2 :: Optic (Get a g1)).
        ( Gettable a g1
        , b ~ Get a g1
        , Gettable b g2
        ) => Gettable a (g1 :.: g2) where
  type Get a (g1 :.: g2) = Get (Get a g1) g2

but GHC complains that it can't match kinds:

    • Expected kind ‘Optic b’, but ‘g2’ has kind ‘Optic (Get a g1)’
    • In the second argument of ‘Gettable’, namely ‘g2’
      In the instance declaration for ‘Gettable a (g1 :.: g2)’
20 |         , Gettable b g2

I don't know if there is a way around that, and I'd be interested to hear any advice.

Change History (5)

comment:1 Changed 11 months ago by RyanGlScott

Milestone: 8.6.3
Priority: normalhighest

First, this appears to be a regression from GHC 8.4, which simply gives an error message:

$ /opt/ghc/8.4.4/bin/ghci Bug.hs -XTypeInType
GHCi, version 8.4.4: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Main             ( Bug.hs, interpreted )

Bug.hs:30:34: error:
    • Expected kind ‘Optic a’, but ‘g2’ has kind ‘Optic b’
    • In the second argument of ‘Get’, namely ‘g2’
      In the type ‘Get a g2’
      In the type instance declaration for ‘Get’
30 |   type Get a (g1 :.: g2) = Get a g2
   |                                  ^^

So that's not good. I'll mark this as highest priority as a result.

Second, the error message:

    • Expected kind ‘Optic b’, but ‘g2’ has kind ‘Optic (Get a g1)’
    • In the second argument of ‘Gettable’, namely ‘g2’
      In the instance declaration for ‘Gettable a (g1 :.: g2)’
20 |         , Gettable b g2

Is actually expected behavior (at least, at the moment). Even though you've written b ~ Get a g1, GHC isn't able to make use of this fact at the type level yet. See #12677/#15710 for the tickets tracking this infelicity.

comment:2 Changed 11 months ago by RyanGlScott

The regression was introduced in commit faec8d358985e5d0bf363bd96f23fe76c9e281f7 (Track type variable scope more carefully.).

comment:3 Changed 11 months ago by simonpj

I know why the crash happens.

  • In the instance decl we bring into scope the skolems of the instance
  • Then, we process the local family instance equation. In doing so we call the dreaded tcFamTyPats -- and it calls solveEqualities (wrongly I believe)
  • This solveEqualities tries to report an error; but it can't see the skolems, hence the panic.

Really solveEqualities should only be called in an empty type environment.

comment:4 Changed 11 months ago by Simon Peyton Jones <simonpj@…>

In 2257a86d/ghc:

Taming the Kind Inference Monster

My original goal was (Trac #15809) to move towards using level numbers
as the basis for deciding which type variables to generalise, rather
than searching for the free varaibles of the environment.  However
it has turned into a truly major refactoring of the kind inference

Let's deal with the level-numbers part first:

* Augment quantifyTyVars to calculate the type variables to
  quantify using level numbers, and compare the result with
  the existing approach.  That is; no change in behaviour,
  just a WARNing if the two approaches give different answers.

* To do this I had to get the level number right when calling
  quantifyTyVars, and this entailed a bit of care, especially
  in the code for kind-checking type declarations.

* However, on the way I was able to eliminate or simplify
  a number of calls to solveEqualities.

This work is incomplete: I'm not /using/ level numbers yet.
When I subsequently get rid of any remaining WARNings in
quantifyTyVars, that the level-number answers differ from
the current answers, then I can rip out the current
"free vars of the environment" stuff.

Anyway, this led me into deep dive into kind inference for type and
class declarations, which is an increasingly soggy part of GHC.
Richard already did some good work recently in

   commit 5e45ad10ffca1ad175b10f6ef3327e1ed8ba25f3
   Date:   Thu Sep 13 09:56:02 2018 +0200

    Finish fix for #14880.

    The real change that fixes the ticket is described in
    Note [Naughty quantification candidates] in TcMType.

but I kept turning over stones. So this patch has ended up
with a pretty significant refactoring of that code too.

Kind inference for types and classes

* Major refactoring in the way we generalise the inferred kind of
  a TyCon, in kcTyClGroup.  Indeed, I made it into a new top-level
  function, generaliseTcTyCon.  Plus a new Note to explain it
  Note [Inferring kinds for type declarations].

* We decided (Trac #15592) not to treat class type variables specially
  when dealing with Inferred/Specified/Required for associated types.
  That simplifies things quite a bit. I also rewrote
  Note [Required, Specified, and Inferred for types]

* Major refactoring of the crucial function kcLHsQTyVars:
  I split it into
       kcLHsQTyVars_Cusk  and  kcLHsQTyVars_NonCusk
  because the two are really quite different. The CUSK case is
  almost entirely rewritten, and is much easier because of our new
  decision not to treat the class variables specially

* I moved all the error checks from tcTyClTyVars (which was a bizarre
  place for it) into generaliseTcTyCon and/or the CUSK case of
  kcLHsQTyVars.  Now tcTyClTyVars is extremely simple.

* I got rid of all the all the subtleties in tcImplicitTKBndrs. Indeed
  now there is no difference between tcImplicitTKBndrs and
  kcImplicitTKBndrs; there is now a single bindImplicitTKBndrs.
  Same for kc/tcExplicitTKBndrs.  None of them monkey with level
  numbers, nor build implication constraints.  scopeTyVars is gone
  entirely, as is kcLHsQTyVarBndrs. It's vastly simpler.

  I found I could get rid of kcLHsQTyVarBndrs entirely, in favour of
  the bnew bindExplicitTKBndrs.

* I now deal with the "naughty quantification candidates"
  of the previous patch in candidateQTyVars, rather than in
  quantifyTyVars; see Note [Naughty quantification candidates]
  in TcMType.

  I also killed off closeOverKindsCQTvs in favour of the same
  strategy that we use for tyCoVarsOfType: namely, close over kinds
  at the occurrences.

  And candidateQTyVars no longer needs a gbl_tvs argument.

* Passing the ContextKind, rather than the expected kind itself,
  to tc_hs_sig_type_and_gen makes it easy to allocate the expected
  result kind (when we are in inference mode) at the right level.

Type families
* I did a major rewrite of the impenetrable tcFamTyPats. The result
  is vastly more comprehensible.

* I got rid of kcDataDefn entirely, quite a big function.

* I re-did the way that checkConsistentFamInst works, so
  that it allows alpha-renaming of invisible arguments.

* The interaction of kind signatures and family instances is tricky.
    Type families: see Note [Apparently-nullary families]
    Data families: see Note [Result kind signature for a data family instance]
                   and Note [Eta-reduction for data families]

* The consistent instantation of an associated type family is tricky.
  See Note [Checking consistent instantiation] and
      Note [Matching in the consistent-instantation check]
  in TcTyClsDecls.  It's now checked in TcTyClsDecls because that is
  when we have the relevant info to hand.

* I got tired of the compromises in etaExpandFamInst, so I did the
  job properly by adding a field cab_eta_tvs to CoAxBranch.
  See Coercion.etaExpandCoAxBranch.

tcInferApps and friends
* I got rid of the mysterious and horrible ClsInstInfo argument
  to tcInferApps, checkExpectedKindX, and various checkValid
  functions.  It was horrible!

* I got rid of [Type] result of tcInferApps.  This list was used
  only in tcFamTyPats, when checking the LHS of a type instance;
  and if there is a cast in the middle, the list is meaningless.
  So I made tcInferApps simpler, and moved the complexity
  (not much) to tcInferApps.

  Result: tcInferApps is now pretty comprehensible again.

* I refactored the many function in TcMType that instantiate skolems.

Smaller things

* I rejigged the error message in checkValidTelescope; I think it's
  quite a bit better now.

* checkValidType was not rejecting constraints in a kind signature
     forall (a :: Eq b => blah). blah2
  That led to further errors when we then do an ambiguity check.
  So I make checkValidType reject it more aggressively.

* I killed off quantifyConDecl, instead calling kindGeneralize

* I fixed an outright bug in tyCoVarsOfImplic, where we were not
  colleting the tyvar of the kind of the skolems

* Renamed ClsInstInfo to AssocInstInfo, and made it into its
  own data type

* Some fiddling around with pretty-printing of family
  instances which was trickier than I thought.  I wanted
  wildcards to print as plain "_" in user messages, although
  they each need a unique identity in the CoAxBranch.

Some other oddments

* Refactoring around the trace messages from reportUnsolved.
* A bit of extra tc-tracing in TcHsSyn.commitFlexi

This patch fixes a raft of bugs, and includes tests for them.

 * #14887
 * #15740
 * #15764
 * #15789
 * #15804
 * #15817
 * #15870
 * #15874
 * #15881

comment:5 Changed 11 months ago by simonpj

Resolution: fixed
Status: newclosed
Test Case: indexed-types/should_fail/T15870
Note: See TracTickets for help on using tickets.