[GHC] #14828: panic! when using :print on some functions with class constraints?
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Keywords: | Operating System: Linux Architecture: x86_64 | Type of failure: Compile-time (amd64) | crash or panic Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- These are the problematic ones I've found: {{{
:t foldl foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b :print foldl ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1H7[rt] :: TYPE t_a1H6[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
:t fmap fmap :: Functor f => (a -> b) -> f a -> f b :print fmap ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1Hu[rt] :: TYPE t_a1Ht[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
:t return return :: Monad m => a -> m a :print return ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1Wt[rt] :: TYPE t_a1Ws[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
:t pure pure :: Applicative f => a -> f a :print pure ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1WP[rt] :: TYPE t_a1WO[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug }}} These that don't have constraints are fine: {{{
:print id id = (_t1::a -> a) :print map map = (_t2::(a1 -> b) -> [a1] -> [b]) :print const const = (_t3::a2 -> b1 -> a2) }}}
This value and function created in the session are fine: {{{
let x :: Monad m => m (); x = return () Prelude| :p x x = (_t5::Monad m1 => m1 ()) let f :: Monad m => Int -> m Int; f n = return (n + 1) Prelude| :p f f = (_t6::Monad m2 => Int -> m2 Int) }}}
mempty and mappend imported from Data.Monoid are fine: {{{
:m + Data.Monoid :p mempty mempty = (_t7::Monoid a4 => a4) :p mappend mappend = (_t8::Monoid a4 => a4 -> a4 -> a4) }}}
foldl' and foldr imported from Data.List are not fine: {{{
:m + Data.List :p foldl' ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a6Qy[rt] :: TYPE t_a6Qx[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
:p Data.List.foldr ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t2_a6RG[rt] :: TYPE t1_a6RF[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug }}} but `all` and `init` from that same module are fine: {{{
:p Data.List.all all = (_t13::Foldable t1 => (a22 -> Bool) -> t1 a22 -> Bool) :p Data.List.init init = (_t14::[a29] -> [a29]) }}}
So, in a given module, among functions with class constraints, some have the error and others don't. I haven't found a value that's not a function with the error, and I haven't found a function with no class constraints exhibit the error. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: => debugger -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by olligobber): Note this is still an issue in 8.6.2 {{{ GHCi, version 8.6.2: http://www.haskell.org/ghc/ :? for help Prelude> :print fmap ghc: panic! (the 'impossible' happened) (GHC version 8.6.2 for x86_64-unknown-linux): isUnliftedType t1_a1x6[rt] :: TYPE t_a1x5[rt] Call stack: CallStack (from HasCallStack): callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:2021:10 in ghc:Type Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): Adding test in !192. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): I spent some time today digging into why exactly this panic happens. The immediate issue appears to be a hiccup in how the interactive debugger handles higher-rank types, which is surprising, considering that none of the types in the original description appear to be higher-rank. For the time being, just take my word for it that this is true—I'll return to this point later. Here is an example showing that `:print` chokes on a term with a higher- rank type: {{{ GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/rgscott/.ghci λ> f :: (forall a. a -> a) -> b -> b; f g x = g x λ> :print f ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1tY[rt] :: TYPE t_a1tX[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type }}} The fact that the panic mentions `t1_a1tY` is a bit curious... I wonder what happens if we try an older version of GHC? {{{ GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/rgscott/.ghci λ> f :: (forall a. a -> a) -> b -> b; f g x = g x λ> :print f f = (_t1::t1) }}} Ah, this //doesn't// panic on GHC 8.0, so this must be a regression introduced between 8.0 and 8.2. Moreover, note that even in 8.0, `:print f`'s behavior is strange: it prints out a thunk of type `t1` instead of, say, `(forall a. a -> a) -> b -> b`. This must explain where the `t1_a1tY` in the 8.2 panic comes from, since that is the type of `_t1` (with its unique explicitly printed). What changed between GHC 8.0 and 8.2 that would trigger this panic? As it turns out, it's commit e7985ed23ddc68b6a2e4af753578dc1d9e8ab4c9 (` Update levity polymorphism`). Specifically, [https://gitlab.haskell.org/ghc/ghc/commit/e7985ed23dd#7cf100051b3d8b0e1a0d4f... this change]: {{{#!diff diff --git a/compiler/ghci/Debugger.hs b/compiler/ghci/Debugger.hs index 64ac1540aa..4d7f8e3ef0 100644 --- a/compiler/ghci/Debugger.hs +++ b/compiler/ghci/Debugger.hs @@ -28,7 +28,6 @@ import Var hiding ( varName ) import VarSet import UniqFM import Type -import Kind import GHC import Outputable import PprTyThing @@ -78,7 +77,7 @@ pprintClosureCommand bindThings force str = do term_ <- GHC.obtainTermFromId maxBound force id' term <- tidyTermTyVars term_ term' <- if bindThings && - False == isUnliftedTypeKind (termType term) + (not (isUnliftedType (termType term))) then bindSuspensions term else return term -- Before leaving, we compare the type obtained to see if it's more specific }}} I'm not sure if this was Richard's intention, but this patch actually changes the behavior of `:print`. Unlike `isUnlifedTypeKind`, `isUnliftedType` is a partial function. If `isUnliftedType` cannot ascertain with 100% confidence that a type is unlifted, then it throws the `isUnliftedType` panic we saw above. Evidently, GHC isn't 100% confident that `t1_a1tY` is unlifted. This proposes one possible patch. Instead of checking if `not (isUnliftedType (termType term))` returns `True`, we could check is `isLiftedType_maybe (termType term)` returns `Just True`. This "inverts" the check by querying if GHC is 100% certain that `termType term` is //lifted//, and moreover, `isLiftedType_maybe` won't panic if that isn't the case. ----- So why are functions like `fmap`, which appear not to be higher-rank, trigger this panic? `-ddump-rtti` reveals the answer: {{{ GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/rgscott/.ghci λ> :set -ddump-rtti λ> :print fmap Term reconstruction started with initial type forall (f :: * -> *). GHC.Base.Functor f => forall a b. (a -> b) -> f a -> f b Unknown closure: Fun check2 passed add constraint: t1_a1sK[tau:1] = GHC.Base.Functor f0_a1sI[tau:1] => forall a b. (a -> b) -> f0_a1sI[tau:1] a -> f0_a1sI[tau:1] b Term reconstruction completed. Term obtained: _ Type obtained: t1_a1sK[rt] ghc: panic! (the 'impossible' happened) (GHC version 8.2.2 for x86_64-unknown-linux): isUnliftedType t1_a1sK[rt] :: TYPE t_a1sJ[rt] Call stack: CallStack (from HasCallStack): prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1133:58 in ghc:Outputable callStackDoc, called at compiler/utils/Outputable.hs:1137:37 in ghc:Outputable pprPanic, called at compiler/types/Type.hs:1952:10 in ghc:Type }}} In particular, take special notice of these parts: {{{ Term reconstruction started with initial type forall (f :: * -> *). GHC.Base.Functor f => forall a b. (a -> b) -> f a -> f b }}} {{{ add constraint: t1_a1sK[tau:1] = GHC.Base.Functor f0_a1sI[tau:1] => forall a b. (a -> b) -> f0_a1sI[tau:1] a -> f0_a1sI[tau:1] b }}} `:print` starts with the type `forall f. Functor f => forall a b. (a -> b) -> f a -> f b` which, strictly speaking, is higher-rank, as there is a nested use of `forall a b`. Normally, we don't think of `forall`s to the right of `=>` as higher-rank, since we can "float" them out to the front of the type, but `:print` doesn't appear to be doing this, since the `add constraint` logging message says that `t1_a1sK` is equal to `Functor f0 => forall a b. (a -> b) -> f0 a -> f0 b`, where `f0` is a metavariable. Note that `:print` seems to have instantiated `f` with a metavariable, but not `a` or `b`! If `:print` had done that, then `t1_a1sK` would not be higher- rank at all, avoiding this panic in the first place. Of course, even if we did this smarter metavariable instantiation, the problem of higher-rank types crashing `:print` would still linger. This suggests that we should fix the `isUnliftedType` panic first, and then we can worry about future steps like making the type of `fmap` render correctly with `:print`. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ben Gamari <ben@…>): In [changeset:"5b970d8e06c1433066a8c587116f0b22c0f30e22/ghc" 5b970d8/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="5b970d8e06c1433066a8c587116f0b22c0f30e22" testsuite: Add test for #14828 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Marge Bot <ben+marge-bot@…>): In [changeset:"8162eab27101cddb0c822347300640f07110379a/ghc" 8162eab2/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="8162eab27101cddb0c822347300640f07110379a" Remove the GHCi debugger's panicking isUnliftedType check The GHCi debugger has never been that robust in the face of higher-rank types, or even types that are _interally_ higher-rank, such as the types of many class methods (e.g., `fmap`). In GHC 8.2, however, things became even worse, as the debugger would start to _panic_ when a user tries passing the name of a higher-rank thing to `:print`. This all ties back to a strange `isUnliftedType` check in `Debugger` that was mysteriously added 11 years ago (in commit 4d71f5ee6dbbfedb4a55767e4375f4c0aadf70bb) with no explanation whatsoever. After some experimentation, no one is quite sure what this `isUnliftedType` check is actually accomplishing. The test suite still passes if it's removed, and I am unable to observe any differences in debugger before even with data types that _do_ have fields of unlifted types (e.g., `data T = MkT Int#`). Given that this is actively causing problems (see #14828), the prudent thing to do seems to be just removing this `isUnliftedType` check, and waiting to see if anyone shouts about it. This patch accomplishes just that. Note that this patch fix the underlying issues behind #14828, as the debugger will still print unhelpful info if you try this: ``` λ> f :: (forall a. a -> a) -> b -> b; f g x = g x λ> :print f f = (_t1::t1) ``` But fixing this will require much more work, so let's start with the simple stuff for now. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14828: panic! when using :print on some functions with class constraints? -------------------------------------+------------------------------------- Reporter: jol | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.2.2 Resolution: | Keywords: debugger Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Marge Bot <ben+marge-bot@…>): In [changeset:"8d18a873c5d7688c6e7d91efab6bb0d6f99393c6/ghc" 8d18a873/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="8d18a873c5d7688c6e7d91efab6bb0d6f99393c6" Reject nested predicates in impredicativity checking When GHC attempts to unify a metavariable with a type containing foralls, it will be rejected as an occurrence of impredicativity. GHC was /not/ extending the same treatment to predicate types, such as in the following (erroneous) example from #11514: ```haskell foo :: forall a. (Show a => a -> a) -> () foo = undefined ``` This will attempt to instantiate `undefined` at `(Show a => a -> a) -> ()`, which is impredicative. This patch catches impredicativity arising from predicates in this fashion. Since GHC is pickier about impredicative instantiations, some test cases needed to be updated to be updated so as not to fall afoul of the new validity check. (There were a surprising number of impredicative uses of `undefined`!) Moreover, the `T14828` test case now has slightly less informative types shown with `:print`. This is due to a a much deeper issue with the GHCi debugger (see #14828). Fixes #11514. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14828#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC