Opened 11 months ago

Last modified 10 months ago

#16127 new bug

Panic: piResultTys1 in compiler/types/Type.hs:1022:5

Reported by: _deepfire Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 8.6.1
Keywords: hs-boot Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Compile-time crash or panic Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by _deepfire)

I apologize in advance for a non-minimised repro.

The panic (with a small -ddump-tc-trace excerpt, but full log also attached):

tcPolyExprNC
  Check{Vocab
          *
          (k_a4TNy[tau:2] -> Constraint)
          i_a4TNv[tau:2]
          (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])}
tcSkolemise
tcInferId
  voc_a4TB2 :: Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
tcCheckId
  voc_a4TB2
  Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  Check{Vocab
          *
          (k_a4TNy[tau:2] -> Constraint)
          i_a4TNv[tau:2]
          (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])}
tcWrapResult
  Actual:   Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  Expected: Check{Vocab
                    *
                    (k_a4TNy[tau:2] -> Constraint)
                    i_a4TNv[tau:2]
                    (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])}
tc_sub_type_ds
  ty_actual   = Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  ty_expected = Vocab
                  *
                  (k_a4TNy[tau:2] -> Constraint)
                  i_a4TNv[tau:2]
                  (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])
deeply_instantiate final subst
  origin: arising from a use of ‘voc_a4TB2’
  type: Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  new type: Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  subst: [TCvSubst
            In scope: InScope {i_a4TMf}
            Type env: []
            Co env: []]
u_tys
  tclvl 2
  Vocab i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
  ~
  Vocab
    *
    (k_a4TNy[tau:2] -> Constraint)
    i_a4TNv[tau:2]
    (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])
  arising from a type equality Vocab
                                 i_a4TMf[sk:1] (Present * * i_a4TMf[sk:1])
                               ~
                               Vocab
                                 *
                                 (k_a4TNy[tau:2] -> Constraint)
                                 i_a4TNv[tau:2]
                                 (Present * k_a4TNy[tau:2] i_a4TNv[tau:2])

<no location info>: error:
    ghc: panic! (the 'impossible' happened)
  (GHC version 8.6.1 for x86_64-unknown-linux):
        piResultTys1
  *
  [i_a4TNv[tau:2], Present * k_a4TNy[tau:2] i_a4TNv[tau:2]]
  Call stack:
      CallStack (from HasCallStack):
        callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
        pprPanic, called at compiler/types/Type.hs:1022:5 in ghc:Type

Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug

Repro (requires Nix & some download time, provides hard repro guarantees in return):

$ git clone https://github.com/deepfire/holotype
$ cd holotype
$ git reset --hard 5c80e9239a3c18d67106920db8f832abc7bd9a93
$ nix-shell
[nix-shell:~/holotype]$ cabal build lib:holotype

Attachments (1)

ghc.out.xz (57.9 KB) - added by _deepfire 11 months ago.
Repro output

Download all attachments as: .zip

Change History (16)

Changed 11 months ago by _deepfire

Attachment: ghc.out.xz added

Repro output

comment:1 Changed 11 months ago by _deepfire

Description: modified (diff)

comment:2 Changed 11 months ago by _deepfire

Description: modified (diff)

comment:3 Changed 11 months ago by _deepfire

..and the following is what hints at the cause (kind polymoprhism mismatch between .hs and .hs-boot) -- the change eliminates the bug:

$ git diff HEAD~1..
diff --git a/src/Holo/Widget2.hs-boot b/src/Holo/Widget2.hs-boot
index d63c757..13ed889 100644
--- a/src/Holo/Widget2.hs-boot
+++ b/src/Holo/Widget2.hs-boot
@@ -3,6 +3,7 @@ where

 import           Data.Kind                                (Type)
 import qualified Data.TypeMap.Dynamic              as TM
+import           GHC.Types                                (Constraint)
 import           Generics.SOP                             (Top)
 import           Generics.SOP.Monadic                     (Result)
 import           Reflex                                   (Dynamic)
@@ -15,7 +16,7 @@ import {-# SOURCE #-}

 data Definition i a

-newtype Vocab i c = Vocab (TM.TypeMap (HoloTag i))
+newtype Vocab (i ∷ Type) (c ∷ Type → Constraint) = Vocab (TM.TypeMap (HoloTag i))
 data                                   HoloTag i

 type Blank   i     = Item Top PBlank
Last edited 11 months ago by _deepfire (previous) (diff)

comment:4 Changed 11 months ago by _deepfire

Commit b87f5bf56e75042e4a55b5b806f6ff24021ea040 on the ghc-16127-repros branch of the holotype repository partially minimises the involved modules.

comment:5 Changed 11 months ago by RyanGlScott

Alas, I can't follow the directions to reproduce this, as it fails quite early for me:

$ nix-shell
unpacking 'https://github.com/NixOS/nixpkgs/archive/cd68a8c7cc602e75a4abbadc94663347a73ae24e.tar.gz'...                                                                                               
error: undefined variable 'stdenv' at /home/rgscott/Documents/Hacking/Haskell/holotype/manual-overrides.nix:24:15                                                                                     
(use '--show-trace' to show detailed location information)

If you could produce a reproducible example without the steep requirement to install Nix or reflex, that would be greatly helpful.

comment:6 Changed 11 months ago by _deepfire

Description: modified (diff)

Ryan, I apologize for the repro fiasco -- I've reproduced your problem in a different environment and fixed it in commit 5c80e9239a3c18d67106920db8f832abc7bd9a93. .

comment:7 Changed 11 months ago by RyanGlScott

This can be minimized down to the following four modules:

-- A.hs
module A where

import {-# SOURCE #-} B

data T i = MkT i

thisPanics :: x
thisPanics = method (MkT 'a')
-- A.hs-boot
{-# LANGUAGE PolyKinds #-}
module A where

data T i
-- B.hs
module B where

import A

class C i where
  method :: T i -> x
-- B.hs-boot
module B where

import {-# SOURCE #-} A

class C i where
  method :: T i -> x

$ /opt/ghc/8.6.3/bin/ghc A.hs
[1 of 4] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 4] Compiling B[boot]          ( B.hs-boot, B.o-boot )
[3 of 4] Compiling A                ( A.hs, A.o )
ghc: panic! (the 'impossible' happened)
  (GHC version 8.6.3 for x86_64-unknown-linux):
        piResultTys1
  *
  [i_aYf[tau:1]]
  Call stack:
      CallStack (from HasCallStack):
        callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
        pprPanic, called at compiler/types/Type.hs:1022:5 in ghc:Type
Last edited 11 months ago by RyanGlScott (previous) (diff)

comment:8 Changed 10 months ago by simonpj

I know what is happening. In A.hs-boot (which has -XPolyKinds) we have

T :: forall k. k  -> Type

Then in B.hs-boot we have

method :: forall i x. C i => T @Type i -> x

When compiling A.hs (no -XPolyKinds) we get

T :: Type -> Type

Now, when we deserialise that imported singature for method we construct the ill-kinded type T @Type i. Result, disaster.

comment:9 Changed 10 months ago by simonpj

What to do? The real problem is that if A.hs defines a type T differently than A.hs-boot, then anything imported into A whose type or kind mentions T is going to be ill-kinded.

So I think the Right Thing is

  • Immediately after typechecking a type/class declaration T, check if there is a hs-boot file definition for it; if so, compare, and fail if there is a mis-match.

Currently the hs-boot file comparison happens all at the end, so this would require a little re-plumbing.

But before doing that, let's check that everyone agrees. (Now that we know the cause, it should be easy to make an even simpler repro case.)

comment:10 Changed 10 months ago by goldfire

Could this happen without the -XPolyKinds disparity? It sounds like "yes". If that's the case, then I agree with your plan.

If the only way this happens is the -XPolyKinds disparity, then I would want to think about this other option: Brutally require that an .hs-boot file and its regular-module counterpart have exactly the same set of extensions enabled. This could be checked very early on, halting with an appropriate error message before ever looking at declarations.

comment:11 Changed 10 months ago by simonpj

Yes, I believe it could happens simply if the T in A.hs-boot differs from the T in A.hs; eg differently-kinded arguments. But I have not tried to cause crashes/Lint errors by doing this; that'd be a good thing to try.

comment:12 Changed 10 months ago by goldfire

That's what I thought -- the kind disparity could be brought about in a number of ways. Yes, it seems the only real way to fix this is more eager consistency checking between .hs-boot files and .hs files.

comment:13 Changed 10 months ago by RyanGlScott

For the sake of completeness, here is a variant of the program suite in comment:7 that exhibits the same panic by providing different numbers of arguments to T instead of using PolyKinds:

-- A.hs
module A where

import {-# SOURCE #-} B

data T i = MkT i

thisPanics :: x
thisPanics = method (MkT 'a')
-- A.hs-boot
module A where

data T i1 i2
-- B.hs
module B where

import A

class C i where
  method :: T i -> x
-- B.hs-boot
module B where

import {-# SOURCE #-} A

class C i where
  method :: T i a -> x

$ /opt/ghc/8.6.3/bin/ghc A.hs
[1 of 4] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 4] Compiling B[boot]          ( B.hs-boot, B.o-boot )
[3 of 4] Compiling A                ( A.hs, A.o )
ghc: panic! (the 'impossible' happened)
  (GHC version 8.6.3 for x86_64-unknown-linux):
        piResultTys1
  *
  [a_aYd[tau:1]]
  Call stack:
      CallStack (from HasCallStack):
        callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
        pprPanic, called at compiler/types/Type.hs:1022:5 in ghc:Type

comment:14 Changed 10 months ago by simonpj

Thanks. I think it should also be easy to provoke with only one one hs-boot file; and with no classes.

comment:15 Changed 10 months ago by simonpj

Keywords: hs-boot added

I'm snowed under at the moment, but this ticket would not be hard to solve for someone who is wanting to help in typechecker-land. I know what to do, and can advise.

Note: See TracTickets for help on using tickets.