I've been trying to make Conal's ConCat plugin work for polymorphic
code, and am running into some problems with the ghc doing that, and I'd
very much appreciate help with that.

Background: I'm trying to get -dcore-lint to flag when my actual problem
happens (has to do with dictionary construction, but it fails earlier
with another problem, which I think comes from the simplifier.

tl;dr: This transformation seems to me problematic:

https://ghc-compiler-notes.readthedocs.io/en/latest/notes/compiler/simplCore/Simplify.hs.html#note-case-to-let-transformation

The docs for the transformation say that it makes this replacement:

case a +# b of r -> …r… into let r = a +# b in …r…

But this creates a let binding with an unlifted binder, which the linter
does not like:

<no location info>: warning:
    [RHS of ... :: Int#]
    The type of this binder is unlifted: ...
    Binder's type: Int#

Arguably, this rule might expect the let to be inlined, but we're seeing
that the let stands, and the linter complains.

My immediate concern is getting around this problem somehow so I can run
the linter on later output of the simplifier.  Is there any way to do
this?  I.e. don't stop when the linter complains, somehow massage the
rules to work better - see below.  Any help would be much appreciated!
(I'm using ghc 8.8.3.)

More details:

The ConCat code has this rule:

"rebox2" [~0] (+#) = \ u# v# -> unboxI (addC (boxI u#, boxI v#))

It fires like this:

Rule fired
    Rule: rebox_2
    Module: (ConCat.Rebox)
    Before: GHC.Prim.+# ValArg 10# ValArg 1#
    After:  (\ (u#_aM4G :: GHC.Prim.Int#) (v#_aM4H :: GHC.Prim.Int#) ->
               ConCat.Rebox.unboxI
                 (ConCat.AltCat.addC
                    @ (->)
                    @ GHC.Types.Int
                    (ConCat.Category.$fNumCat->a @ GHC.Types.Int 
GHC.Num.$fNumInt)
                    (ConCat.Rebox.boxI u#_aM4G, ConCat.Rebox.boxI v#_aM4H)))
              10# 1#
    Cont:   Stop[BoringCtxt] GHC.Prim.Int#

... and comes out of the simplifier like this:

let {
  n1_sM4V :: GHC.Prim.Int#
  [LclId,
   Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False,
           WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 110 0}]
  n1_sM4V
    = case ConCat.AltCat.addC
             @ (->)
             @ GHC.Types.Int
             (ConCat.Category.$fNumCat->a
                @ GHC.Types.Int GHC.Num.$fNumInt)
             (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
      of
      { GHC.Types.I# i#_aM4S ->
      i#_aM4S
      } } in
GHC.Types.I#
  (case ConCat.AltCat.addC
          @ (->)
          @ GHC.Types.Int
          (ConCat.Category.$fNumCat->a @ GHC.Types.Int GHC.Num.$fNumInt)
          (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
   of
   { GHC.Types.I# i#_aM4S ->
   i#_aM4S
   }) } in ...

Ironically, you can see that the simplifier already *has* inlined, just
not elided the (now dead) let binding yet, before the linter gets to it.

I've also attached a shorter source file with the relevant rules that
triggers the linter, albeit with a different message.

Richard Eisenberg, Gabor Greif, and Conal helped me get to this point.
Many thanks to them!

-- 
Regards,
Mike
{-# LANGUAGE MagicHash #-}
{-# OPTIONS_GHC -frewrite-rules #-}
{-# OPTIONS_GHC -ddump-rule-rewrites #-}
{-# OPTIONS_GHC -ddump-rules #-}
{-# OPTIONS_GHC -dcore-lint #-}
{-# OPTIONS_GHC -ddump-simpl #-}

module ConCatRules where

import GHC.Prim
import GHC.Int

boxI :: Int# -> Int
boxI = I#
{-# INLINE [0] boxI #-}

unboxI :: Int -> Int#
unboxI (I# i#) = i#
-- {-# INLINE [0] unboxI #-}

plus :: Int -> Int -> Int
plus x y = undefined
{-# NOINLINE plus #-}

{-# RULES
"reboxa" forall u# v# . (+#) u# v# = unboxI (plus (boxI u#) (boxI v#))
"reboxb" forall u# . (+#) u# = \v# -> unboxI (plus (boxI u#) (boxI v#))
"reboxc" (+#) = \ u# v# -> unboxI (plus (boxI u#) (boxI v#))
#-}

foo = I# (10# +# 1#)
_______________________________________________
ghc-devs mailing list
[email protected]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Reply via email to