Ticket #7364 (closed bug: wontfix)

Opened 7 months ago

Last modified 6 months ago

`foo !f = id . f` becomes non-strict with -O2

Reported by: shachaf Owned by:
Priority: normal Milestone: _|_
Component: Compiler Version: 7.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

The following program:

foo :: (a -> b) -> a -> b
foo !f = id . f

main :: IO ()
main = print (foo undefined `seq` "ok")

Crashes with Prelude.undefined when compiled without -O2, but prints "ok" with it. As far as I can tell the optimizer shouldn't be allowed to do that.

Change History

Changed 7 months ago by ezyang

Looks like a bug in the specializer.

ezyang@javelin:~/Dev/haskell$ ../ghc-build-master/inplace/bin/ghc-stage2 strict.hs -fforce-recomp -O -ddump-spec
[1 of 1] Compiling Main             ( strict.hs, strict.o )

==================== Specialise ====================
Result size of Specialise = {terms: 19, types: 27, coercions: 10}

a_sn2
  :: GHC.Prim.State# GHC.Prim.RealWorld
     -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #)
[LclId,
 Arity=1,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=1, Value=True,
         ConLike=True, WorkFree=True, Expandable=True,
         Guidance=IF_ARGS [0] 91 60}]
a_sn2 =
  \ (eta_B1 :: GHC.Prim.State# GHC.Prim.RealWorld) ->
    ((System.IO.print
        @ [GHC.Types.Char]
        (GHC.Show.$fShow[] @ GHC.Types.Char GHC.Show.$fShowChar)
        (GHC.Base.build
           @ GHC.Types.Char
           (\ (@ b_amP) -> GHC.CString.unpackFoldrCString# @ b_amP "ok"#)))
     `cast` (GHC.Types.NTCo:IO <()>
             :: GHC.Types.IO ()
                  ~#
                (GHC.Prim.State# GHC.Prim.RealWorld
                 -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))))
      eta_B1

Main.main :: GHC.Types.IO ()
[LclIdX,
 Arity=1,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=True,
         ConLike=True, WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=True)}]
Main.main =
  a_sn2
  `cast` (Sym (GHC.Types.NTCo:IO <()>)
          :: (GHC.Prim.State# GHC.Prim.RealWorld
              -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))
               ~#
             GHC.Types.IO ())

a_sn4
  :: GHC.Prim.State# GHC.Prim.RealWorld
     -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #)
[LclId,
 Arity=1,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=1, Value=True,
         ConLike=True, WorkFree=True, Expandable=True,
         Guidance=IF_ARGS [0] 21 60}]
a_sn4 =
  \ (eta_Xb :: GHC.Prim.State# GHC.Prim.RealWorld) ->
    ((GHC.TopHandler.runMainIO @ () Main.main)
     `cast` (GHC.Types.NTCo:IO <()>
             :: GHC.Types.IO ()
                  ~#
                (GHC.Prim.State# GHC.Prim.RealWorld
                 -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))))
      eta_Xb

:Main.main :: GHC.Types.IO ()
[LclIdX,
 Arity=1,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=True,
         ConLike=True, WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=True)}]
:Main.main =
  a_sn4
  `cast` (Sym (GHC.Types.NTCo:IO <()>)
          :: (GHC.Prim.State# GHC.Prim.RealWorld
              -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))
               ~#
             GHC.Types.IO ())



Linking strict ...

Changed 7 months ago by ezyang

Oh, not true, I'm confused about pass ordering; it is a problem with the simplifier, not the specializer.

Changed 6 months ago by simonpj

  • difficulty set to Unknown
  • milestone set to _|_

Indeed. See #5587 and the user manual section. I still don't know how to get good optimisation without accepting this infelicity. Better ideas welcome.

Simon

Changed 6 months ago by simonmar

#5587 is marked fixed; maybe we should do the same with this one?

Changed 6 months ago by simonpj

Or maybe we should mark both as not-fixed. There is an underlying problem here; it's just that we don't know how to solve it.

Changed 6 months ago by simonmar

  • status changed from new to closed
  • resolution set to wontfix

Yes, good idea - closing as wonfix (the closest we have to "not fixed")

Note: See TracTickets for help on using tickets.