Opened 2 years ago

Closed 2 years ago

#13710 closed bug (fixed)

panic with boot and -jX

Reported by: pacak Owned by:
Priority: normal Milestone: 8.4.1
Component: Compiler Version: 8.2.1-rc2
Keywords: hs-boot Cc: ezyang
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): Phab:D3743
Wiki Page:

Description

% cat A.hs
module A where
% cat A.hs-boot
module A ( A ) where

type A = Maybe ()

yay :: A -> IO ()
% cat B.hs
module B where

import {-# SOURCE #-} A

This panics:

% rm -rf o ; ghc -j2 -outputdir o B
[1 of 3] Compiling A[boot]          ( A.hs-boot, o/A.o-boot )
[2 of 3] Compiling A                ( A.hs, o/A.o )

<no location info>: error:
    ghc: panic! (the 'impossible' happened)
  (GHC version 8.2.0.20170503 for x86_64-unknown-linux):
        tcIfaceGlobal (local): not found
  You are in a maze of twisty little passages, all alike.
  While forcing the thunk for TyThing A
  which was lazily initialized by initIfaceCheck typecheckLoop,
  I tried to tie the knot, but I couldn't find A
  in the current type environment.
  If you are developing GHC, please read Note [Tying the knot]
  and Note [Type-checking inside the knot].
  Consider rebuilding GHC with profiling for a better stack trace.
  Contents of current type environment:
    [r15J :-> Identifier ‘$trModule’]
  Call stack:
      CallStack (from HasCallStack):
        prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1134:58 in ghc:Outputable
        callStackDoc, called at compiler/utils/Outputable.hs:1138:37 in ghc:Outputable
        pprPanic, called at compiler/iface/TcIface.hs:1689:23 in ghc:TcIface

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

This works:

% rm -rf o ; ghc -j1 -outputdir o B
[1 of 3] Compiling A[boot]          ( A.hs-boot, o/A.o-boot )
[2 of 3] Compiling A                ( A.hs, o/A.o )

A.hs-boot:3:1: error:
    ‘A.A’ is exported by the hs-boot file, but not exported by the module
  |
3 | type A = Maybe ()
  | ^^^^^^^^^^^^^^^^^

Change History (19)

comment:1 Changed 2 years ago by pacak

works as expected in 8.0

comment:2 Changed 2 years ago by simonpj

Cc: ezyang added

I think this is Edward's error message.

Edward might you look?

Simon

comment:3 Changed 2 years ago by ezyang

Keywords: hs-boot added

comment:4 Changed 2 years ago by ezyang

This bug is kind of similar to #12063, in that the panic is induced when we attempt to use interfaces prior to having checked that everything is squared away. The interface usage is probably related to parallel mode. I'll take a look.

comment:5 Changed 2 years ago by pacak

It might be slightly different from the bug you mentioned - it was minimized from code that compiles fine with 8.0 and panics with r 2, but before minimization it wanted like a half of hackage to compile.

comment:6 Changed 2 years ago by pacak

In original code there's no effect from -j1 - it still panics.

comment:7 Changed 2 years ago by ezyang

So, I think this particular repro case may have been minimized too much. It's known that we have some bugs handling hs-boot typechecking when the typechecking would ultimately fail (as it would in this example, since the implementer doesn't implement enough), but if the original test case was code that "should" compile, then it would be better if we had a test case which similarly should compile.

comment:8 Changed 2 years ago by pacak

Panic in rc2, successfull compilation in 8.0 and 7.10

% cat A.hs
{-# LANGUAGE RecordWildCards #-}

module A where

import B

type E = ()

yay :: Maybe ()
yay = do
  H{..} <- undefined
  undefined
% cat A.hs-boot
module A ( E ) where
type E = ()
% cat B.hs
module B where
import {-# SOURCE #-} A
data F a = F a
type G = F (Maybe E)
data H = H { h :: {-# UNPACK #-} !G }

rc2, -j1

% rm *.hi* *.o* ; ghc -j1 -O2 A.hs
[1 of 3] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling A                ( A.hs, A.o )
ghc: panic! (the 'impossible' happened)
  (GHC version 8.2.0.20170503 for x86_64-unknown-linux):
        tcIfaceGlobal (local): not found
  You are in a maze of twisty little passages, all alike.
  While forcing the thunk for TyThing E
  which was lazily initialized by initIfaceCheck typecheckLoop,
  I tried to tie the knot, but I couldn't find E
  in the current type environment.
  If you are developing GHC, please read Note [Tying the knot]
  and Note [Type-checking inside the knot].
  Consider rebuilding GHC with profiling for a better stack trace.
  Contents of current type environment: []
  Call stack:
      CallStack (from HasCallStack):
        prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1134:58 in ghc:Outputable
        callStackDoc, called at compiler/utils/Outputable.hs:1138:37 in ghc:Outputable
        pprPanic, called at compiler/iface/TcIface.hs:1689:23 in ghc:TcIface

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

rc2, -j2 - note - error message is slightly different + it's in color

% rm *.hi* *.o* ; ghc -j2 -O2 A.hs
[1 of 3] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling A                ( A.hs, A.o )

<no location info>: error:
    ghc: panic! (the 'impossible' happened)
  (GHC version 8.2.0.20170503 for x86_64-unknown-linux):
        tcIfaceGlobal (local): not found
  You are in a maze of twisty little passages, all alike.
  While forcing the thunk for TyThing E
  which was lazily initialized by initIfaceCheck typecheckLoop,
  I tried to tie the knot, but I couldn't find E
  in the current type environment.
  If you are developing GHC, please read Note [Tying the knot]
  and Note [Type-checking inside the knot].
  Consider rebuilding GHC with profiling for a better stack trace.
  Contents of current type environment: []
  Call stack:
      CallStack (from HasCallStack):
        prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1134:58 in ghc:Outputable
        callStackDoc, called at compiler/utils/Outputable.hs:1138:37 in ghc:Outputable
        pprPanic, called at compiler/iface/TcIface.hs:1689:23 in ghc:TcIface

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

ghc 8.0:

% rm *.hi* *.o* ; ghc -j1 -O2 A.hs
[1 of 3] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling A                ( A.hs, A.o )
% rm *.hi* *.o* ; ghc -j2 -O2 A.hs
[1 of 3] Compiling A[boot]          ( A.hs-boot, A.o-boot )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling A                ( A.hs, A.o )

comment:9 Changed 2 years ago by ezyang

This is a record wild cards problem. Here is a further reduced test case:

-- A.hs
{-# LANGUAGE RecordWildCards #-}
module A where
import B
data E = MkE
p (H{..}) = ()

-- A.hs-boot
module A ( E ) where
data E

-- B.hs
module B where
import {-# SOURCE #-} A
data H = H { h :: E }

Probably what is happening is that record wildcards is forcing the thunk for E during renaming, which is far before it is ready. Workaround should be to replace the record wildcard with explicitly listed out fields.

comment:10 Changed 2 years ago by pacak

Workaround works on real code, thanks.

comment:11 Changed 2 years ago by simonpj

Seems dangerously fragile to me. Can you see a path to fixing it?

comment:12 Changed 2 years ago by ezyang

So... apparently this patch fixes the problem, but I haven't quite figured out why.

diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
index 3a6a4070d2..50fafcdadf 100644
--- a/compiler/iface/TcIface.hs
+++ b/compiler/iface/TcIface.hs
@@ -908,7 +908,8 @@ tcIfaceDataCons tycon_name tycon tc_tybinders if_cons
         ; ~(eq_spec, theta, arg_tys, stricts) <- forkM (mk_doc dc_name) $
              do { eq_spec <- tcIfaceEqSpec spec
                 ; theta   <- tcIfaceCtxt ctxt
-                ; arg_tys <- mapM tcIfaceType args
+                ; arg_tys <- forkM (mk_doc dc_name <+> text "arg_tys")
+                           $ mapM tcIfaceType args
                 ; stricts <- mapM tc_strict if_stricts
                         -- The IfBang field can mention
                         -- the type itself; hence inside forkM

comment:13 Changed 2 years ago by RyanGlScott

Now with even fewer internal dependencies:

{-# LANGUAGE TypeFamilies #-}
module D (D) where

type family D a
type instance D Int = Int
module GIGioInterfacesFile where

import D ()
import {-# SOURCE #-} qualified GIGioObjectsFileEnumerator as Gio.FileEnumerator
import {-# SOURCE #-} qualified GIGioObjectsMountOperation as Gio.MountOperation

class IsFile o

It looks like type family instances are the culprit.

comment:14 Changed 2 years ago by RyanGlScott

Oops, sorry, comment:13 was meant for #13803.

comment:15 Changed 2 years ago by ezyang

Differential Rev(s): Phab:D3743
Status: newpatch

comment:16 Changed 2 years ago by simonpj

Are you sure it's a record wildcard problem? The Description doesn't have any record wildcards.

comment:17 Changed 2 years ago by ezyang

Yeah. The original code was minimized too much: it triggered a panic, but the code wouldn't have typechecked anyway (like #12063). They gave a second repro which does involve record wildcards.

comment:18 Changed 2 years ago by Ben Gamari <ben@…>

In 9e9fb57/ghc:

Fix hs-boot knot-tying with record wild cards.

Fixes #13710.

Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>

Test Plan: validate

Reviewers: bgamari, austin, simonpj

Reviewed By: simonpj

Subscribers: simonpj, rwbarton, thomie

GHC Trac Issues: #13710

Differential Revision: https://phabricator.haskell.org/D3743

comment:19 Changed 2 years ago by bgamari

Milestone: 8.4.1
Resolution: fixed
Status: patchclosed
Note: See TracTickets for help on using tickets.