#14763 closed bug (fixed)

GHC 8.4.1-alpha regression with FunctionalDependencies

Reported by: RyanGlScott Owned by:
Priority: highest Milestone: 8.4.1
Component: Compiler (Type checker) Version: 8.4.1-alpha3
Keywords: FunDeps Cc: simonpj
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Test Case: testsuite/tests/typecheck/should_compile/T14763
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by RyanGlScott)

This regression prevents esqueleto-2.5.3 from building with GHC 8.4.1. Here is a minimized example of the problem:

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Bug where

data Value a = Value a

data SomeValue expr where
  SomeValue :: Esqueleto query expr backend => expr (Value a) -> SomeValue expr

class Esqueleto (query :: * -> *) (expr :: * -> *) backend
        | query -> expr backend, expr -> query backend

data SqlQuery a

data SqlBackend

data SqlExpr a where
  ECompositeKey :: SqlExpr (Value a)

instance Esqueleto SqlQuery SqlExpr SqlBackend

match' :: SomeValue SqlExpr -> a
match' (SomeValue ECompositeKey) = undefined

On GHC 8.2.2, this typechecks without issue. On GHC 8.4.1-alpha (version 8.4.0.20180204), this fails with:

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

Bug.hs:25:19: error:
    • Could not deduce: query ~ SqlQuery
        arising from a functional dependency between:
          constraint ‘Esqueleto query SqlExpr backend’
            arising from a pattern with constructor:
                           SomeValue :: forall (query :: * -> *) (expr :: * -> *) backend a.
                                        Esqueleto query expr backend =>
                                        expr (Value a) -> SomeValue expr,
                         in an equation for ‘match'’
          instance ‘Esqueleto SqlQuery SqlExpr SqlBackend’ at Bug.hs:22:10-46
      from the context: Value a1 ~ Value a2
        bound by a pattern with constructor:
                   ECompositeKey :: forall a. SqlExpr (Value a),
                 in an equation for ‘match'’
        at Bug.hs:25:19-31
      ‘query’ is a rigid type variable bound by
        a pattern with constructor:
          SomeValue :: forall (query :: * -> *) (expr :: * -> *) backend a.
                       Esqueleto query expr backend =>
                       expr (Value a) -> SomeValue expr,
        in an equation for ‘match'’
        at Bug.hs:25:9-31
      Inaccessible code in
        a pattern with constructor:
          ECompositeKey :: forall a. SqlExpr (Value a),
        in an equation for ‘match'’
    • In the pattern: ECompositeKey
      In the pattern: SomeValue ECompositeKey
      In an equation for ‘match'’:
          match' (SomeValue ECompositeKey) = undefined
   |
25 | match' (SomeValue ECompositeKey) = undefined
   |                   ^^^^^^^^^^^^^

Change History (6)

comment:1 Changed 20 months ago by RyanGlScott

Description: modified (diff)

comment:2 Changed 20 months ago by RyanGlScott

Cc: simonpj added

This regression was introduced in f20cf982f126aea968ed6a482551550ffb6650cf (Remove wc_insol from WantedConstraints).

comment:3 Changed 20 months ago by bgamari

Thank you RyanGlScott!

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

In 6edafe3/ghc:

Fix isDroppableCt (Trac #14763)

When finishing up an implication constraint, it's a bit tricky to
decide which Derived constraints to retain (for error reporting) and
which to discard.  I got this wrong in commit
   f20cf982f126aea968ed6a482551550ffb6650cf
   (Remove wc_insol from WantedConstraints)

The particular problem in Trac #14763 was that we were reporting as an
error a fundep-generated constraint
  (ex ~ T)
where 'ex' is an existentially-bound variable in a pattern match.
But this isn't really an error at all.

This patch fixes the problem. Indeed, since I had to understand
this rather tricky code, I took the opportunity to clean it up
and document better.  See
  isDroppableCt :: Ct -> Bool
and Note [Dropping derived constraints]

I also removed wl_deriv altogether from the WorkList data type.  It
was there in the hope of gaining efficiency by not even processing
lots of derived constraints, but it has turned out that most derived
constraints (notably equalities) must be processed anyway; see
Note [Prioritise equalities] in TcSMonad.

The two are coupled because to decide which constraints to put in
wl_deriv I was using another variant of isDroppableCt.  Now it's much
simpler -- and perhaps even more efficient too.

comment:5 Changed 19 months ago by simonpj

Status: newmerge
Test Case: testsuite/tests/typecheck/should_compile/T14763

Thanks for reporting this with a nice small example.

comment:6 Changed 19 months ago by bgamari

Resolution: fixed
Status: mergeclosed
Note: See TracTickets for help on using tickets.