[GHC] #15648: Core Lint error with source-level unboxed equality
GHC
ghc-devs at haskell.org
Sat Sep 15 14:50:24 UTC 2018
#15648: Core Lint error with source-level unboxed equality
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: 8.8.1
Component: Compiler | Version: 8.4.3
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: Compile-time
Unknown/Multiple | crash or panic
Test Case: | Blocked By:
Blocking: | Related Tickets: #15209
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
I thought that we had killed `(~#)` from the source language in #15209. I
could not have been more wrong. Source-level `(~#)` is alive and well, and
it can cause Core Lint errors. Be afraid. Be very, very afraid.
The trick is to grab `(~#)` using Template Haskell:
{{{#!hs
module Foo where
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Syntax
ueqT :: Q Type
ueqT = conT $ mkNameG_tc "ghc-prim" "GHC.Prim" "~#"
}}}
Once this is done, you can plop unboxed equality wherever you want into
the source language. Here is a particularly mischievous example:
{{{#!hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Bug where
import Data.Kind (Type)
import Data.Type.Equality (type (~~))
import Foo (ueqT)
data LegitEquality :: Type -> Type -> Type where
Legit :: LegitEquality a a
data JankyEquality :: Type -> Type -> Type where
Jank :: $ueqT a b -> JankyEquality a b
unJank :: JankyEquality a b -> $ueqT a b
unJank (Jank x) = x
legitToJank :: LegitEquality a b -> JankyEquality a b
legitToJank Legit = Jank
mkLegit :: a ~~ b => LegitEquality a b
mkLegit = Legit
ueqSym :: forall (a :: Type) (b :: Type).
$ueqT a b -> $ueqT b a
ueqSym = unJank $ legitToJank $ mkLegit @b @a
}}}
If you compile this with optimizations, then GHC's inner demons are
unleashed, which brings utter chaos when `-dcore-lint` is enabled:
{{{
$ /opt/ghc/8.6.1/bin/ghc -O2 -fforce-recomp Bug.hs -dcore-lint
[1 of 2] Compiling Foo ( Foo.hs, Foo.o )
[2 of 2] Compiling Bug ( Bug.hs, Bug.o )
*** Core Lint errors : in result of Simplifier ***
<no location info>: warning:
[in body of lambda with binder co_a5RY :: a_a5RV ~# b_a5RW]
x_a5OX :: b_a5RW ~# a_a5RV
[LclId] is out of scope
*** Offending Program ***
<elided>
ueqSym :: forall a b. (a ~# b) => b ~# a
[LclIdX,
Arity=1,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)}]
ueqSym
= \ (@ a_a5RV) (@ b_a5RW) (co_a5RY :: a_a5RV ~# b_a5RW) -> x_a5OX
}}}
-----
Obviously, this ticket is a little tongue-in-cheek, since I'm probably
inviting disaster upon myself by deliberately digging around in `ghc-prim`
for `(~#)`. But this does raise the question: should we allow users to do
this? I used to think that there was no harm in leaving `(~#)` lying at
the bottom of the catacombs that is `ghc-prim`, but this example shows
that perhaps `(~#)` should be locked away for good.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15648>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list