Opened 3 years ago

Closed 3 years ago

#12144 closed bug (fixed)

GHC panic when using DeriveAnyClass with functor-like class and datatype with a type variable in a contravariant position

Reported by: RyanGlScott Owned by:
Priority: normal Milestone: 8.2.1
Component: Compiler Version: 8.0.1
Keywords: Generics Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Compile-time crash Test Case: tests/deriving/should_compile/T12144_1, tests/deriving/should_compile/T12144_2
Blocked By: Blocking:
Related Tickets: #5462, #7346, #12423 Differential Rev(s): Phab:D2961
Wiki Page:

Description

The following code

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE KindSignatures #-}
module Example where

class C (a :: * -> *)
data T a = MkT (a -> Int) deriving C

fails to compile with the following GHC panic:

$ /opt/ghc/8.0.1/bin/ghc Example.hs
[1 of 1] Compiling Example          ( Example.hs, Example.o )
ghc: panic! (the 'impossible' happened)
  (GHC version 8.0.1 for x86_64-unknown-linux):
	contravariant

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

The culprit is that when DeriveAnyClass comes up with the constraints for typeclass instances whose argument is of kind * -> *, it calls deepSubtypesContaining, which immediately bails out when it sees a type variable in a contravariant or "bad" position. I'm less sure of what the fix should be.

Change History (5)

comment:1 Changed 3 years ago by RyanGlScott

comment:2 Changed 3 years ago by RyanGlScott

See also #12423, which throws a very similar panic (but for a slightly more sensible reason).

comment:3 Changed 3 years ago by RyanGlScott

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

A WIP attempt at fixing this is at ​Phab:D2961.

comment:4 Changed 3 years ago by Ryan Scott <ryan.gl.scott@…>

In 639e702/ghc:

Refactor DeriveAnyClass's instance context inference

Summary:
Currently, `DeriveAnyClass` has two glaring flaws:

* It only works on classes whose argument is of kind `*` or `* -> *` (#9821).
* The way it infers constraints makes no sense. It basically co-opts the
  algorithms used to infer contexts for `Eq` (for `*`-kinded arguments) or
  `Functor` (for `(* -> *)`-kinded arguments). This tends to produce overly
  constrained instances, which in extreme cases can lead to legitimate things
  failing to typecheck (#12594). Or even worse, it can trigger GHC panics
  (#12144 and #12423).

This completely reworks the way `DeriveAnyClass` infers constraints to fix
these two issues. It now uses the type signatures of the derived class's
methods to infer constraints (and to simplify them). A high-level description
of how this works is included in the GHC users' guide, and more technical notes
on what is going on can be found as comments (and a Note) in `TcDerivInfer`.

Fixes #9821, #12144, #12423, #12594.

Test Plan: ./validate

Reviewers: dfeuer, goldfire, simonpj, austin, bgamari

Subscribers: dfeuer, thomie

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

comment:5 Changed 3 years ago by RyanGlScott

Resolution: fixed
Status: patchclosed
Test Case: tests/deriving/should_compile/T12144_1, tests/deriving/should_compile/T12144_2
Note: See TracTickets for help on using tickets.