[GHC] #13446: Deferred type error sneaks in with -fno-defer-type-errors enabled

GHC ghc-devs at haskell.org
Sat Mar 18 21:12:38 UTC 2017


#13446: Deferred type error sneaks in with -fno-defer-type-errors enabled
-------------------------------------+-------------------------------------
           Reporter:  RyanGlScott    |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.0.2
  (Type checker)                     |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  GHC accepts
  Unknown/Multiple                   |  invalid program
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 This is a very perplexing bug that MitchellSalad discovered and advertised
 in
 [https://www.reddit.com/r/haskell/comments/604mze/deferred_type_errors_without_setting/
 this Reddit post]. Consider this code:

 {{{#!hs
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# OPTIONS_GHC -fno-defer-type-errors #-}
 module Main where

 import Data.Coerce (Coercible)
 import GHC.Exts (Constraint)
 import GHC.TypeLits (Symbol)

 data Dict :: Constraint -> * where
   Dict :: a => Dict a

 infixr 9 :-
 newtype a :- b = Sub (a => Dict b)
 instance a => Show (a :- b) where
   showsPrec d (Sub Dict) = showParen (d > 10) $ showString "Sub Dict"

 class Lifting p f where
   lifting :: p a :- p (f a)

 data Blah a = Blah

 newtype J (a :: JType) = J (Blah (J a))
 newtype JComparable a = JComparable (J (T (JTy a)))

 instance Lifting JReference JComparable where
   lifting = Sub 'a'

 class (Coercible a (J (JTy a))) => JReference a where
   type JTy a :: JType

 type T a
   = 'Generic ('Iface "java.lang.Comparable") '[a]
 data JType = Class Symbol
            | Generic JType [JType]
            | Iface Symbol
 type JObject = J (Class "java.lang.Object")
 instance JReference JObject where
   type JTy JObject = 'Class "java.lang.Object"

 main :: IO ()
 main = print (lifting :: JReference JObject :- JReference (JComparable
 JObject))
 }}}

 There are three concerning things about this:

 1. Look at the line `lifting = Sub 'a'`. That's obviously bogus, as
 `Char`s are not `Dict`s! Yet GHC 8.0.2 and HEAD readily typecheck this
 code without warnings.
 2. So now that we seem to have circumvented type safety, what happens if
 we actually try to //run// code which uses this bogus `Lifting` instance?
 Something truly bizarre, that's what:

 {{{
 $ /opt/ghc/8.0.2/bin/ghci Bug.hs
 GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
 Loaded GHCi configuration from /home/rgscott/.ghci
 [1 of 1] Compiling Main             ( Bug.hs, interpreted )
 Ok, modules loaded: Main.
 λ> main
 *** Exception: Bug.hs:34:17: error:
     • Couldn't match expected type ‘Dict (JReference (JComparable a))’
                   with actual type ‘Char’
     • In the first argument of ‘Sub’, namely ‘'a'’
       In the expression: Sub 'a'
       In an equation for ‘lifting’: lifting = Sub 'a'
     • Relevant bindings include
         lifting :: JReference a :- JReference (JComparable a)
           (bound at Bug.hs:34:3)
 (deferred type error)
 }}}

    Somehow, we managed to defer a type mismatch between `Char` and `Dict`.
 All while `-fno-defer-type-errors` is enabled!
 3. Worst of all, this is a regression from GHC 8.0.1, as it will actually
 detect the type mismatch at compile-time:

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

 Bug.hs:34:17: error:
     • Couldn't match expected type ‘Dict (JReference (JComparable a))’
                   with actual type ‘Char’
     • In the first argument of ‘Sub’, namely ‘'a'’
       In the expression: Sub 'a'
       In an equation for ‘lifting’: lifting = Sub 'a'
     • Relevant bindings include
         lifting :: JReference a :- JReference (JComparable a)
           (bound at Bug.hs:34:3)
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13446>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list