How to fool the divergence checker in ghc 9

I'm trying to port Conal Elliott's ConCat plugin from ghc 8 to 9, and the divergence checker foils me. Background: The plugin works by transforming calls to a pseudo-function toCcc' defined like so: -- | Pseudo function to trigger rewriting to TOCCC form. toCcc' :: forall k a b. (a -> b) -> (a `k` b) toCcc' _ = oops "toCcc' called" {-# NOINLINE toCcc' #-} For ghc 8, oops was defined like so: module ConCat.Misc where -- | Pseudo function to fool GHC's divergence checker. oops :: String -> b oops str = errorWithStackTrace ("Oops: "++str) {-# NOINLINE oops #-} ... but unfortunately, ghc 9 is not so easily fooled and reports <A>x for toCcc'. Is there any way to prevent this that works for ghc 9? Help would be much appreciated! -- Regards, Mike

I don't know what all that means exactly (especially since GHC's demand
signatures have changed recently in a way I don't understand at all). But
for hiding divergence, one option is to use a module with demand analysis
disabled. Try {-# options_ghc -fno-strictness #-}. You'll likely need to
put oops in its own module to avoid interfering with desired optimizations.
On Fri, Jan 20, 2023, 4:36 AM Michael Sperber
I'm trying to port Conal Elliott's ConCat plugin from ghc 8 to 9, and the divergence checker foils me.
Background: The plugin works by transforming calls to a pseudo-function toCcc' defined like so:
-- | Pseudo function to trigger rewriting to TOCCC form. toCcc' :: forall k a b. (a -> b) -> (a `k` b) toCcc' _ = oops "toCcc' called" {-# NOINLINE toCcc' #-}
For ghc 8, oops was defined like so:
module ConCat.Misc where
-- | Pseudo function to fool GHC's divergence checker. oops :: String -> b oops str = errorWithStackTrace ("Oops: "++str) {-# NOINLINE oops #-}
... but unfortunately, ghc 9 is not so easily fooled and reports <A>x for toCcc'. Is there any way to prevent this that works for ghc 9?
Help would be much appreciated!
-- Regards, Mike _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users

On Fri, Jan 20 2023, David Feuer
I don't know what all that means exactly (especially since GHC's demand signatures have changed recently in a way I don't understand at all). But for hiding divergence, one option is to use a module with demand analysis disabled. Try {-# options_ghc -fno-strictness #-}. You'll likely need to put oops in its own module to avoid interfering with desired optimizations.
THanks for the suggestion! So I did this: {-# options_ghc -fno-strictness #-} module ConCat.Oops(oops) where import GHC.Stack (errorWithStackTrace) -- for oops -- | Pseudo function to fool GHC's divergence checker. oops :: String -> b oops str = errorWithStackTrace ("Oops: "++str) {-# NOINLINE oops #-} ... but am getting the same result from the divergence checker, sadly ... -- Regards, Mike

What if you go with the big hammer for that module: -O0? My main concern
about that is that you won't get arity analysis. There may be some more -f
flags I've missed...
On Fri, Jan 20, 2023, 5:17 AM Michael Sperber
On Fri, Jan 20 2023, David Feuer
wrote: I don't know what all that means exactly (especially since GHC's demand signatures have changed recently in a way I don't understand at all). But for hiding divergence, one option is to use a module with demand analysis disabled. Try {-# options_ghc -fno-strictness #-}. You'll likely need to put oops in its own module to avoid interfering with desired optimizations.
THanks for the suggestion!
So I did this:
{-# options_ghc -fno-strictness #-} module ConCat.Oops(oops) where
import GHC.Stack (errorWithStackTrace) -- for oops
-- | Pseudo function to fool GHC's divergence checker. oops :: String -> b oops str = errorWithStackTrace ("Oops: "++str) {-# NOINLINE oops #-}
... but am getting the same result from the divergence checker, sadly ...
-- Regards, Mike

Actually, getting that arity probably isn't important anyway.... Try O0.
On Fri, Jan 20, 2023, 5:26 AM David Feuer
What if you go with the big hammer for that module: -O0? My main concern about that is that you won't get arity analysis. There may be some more -f flags I've missed...
On Fri, Jan 20, 2023, 5:17 AM Michael Sperber
wrote: On Fri, Jan 20 2023, David Feuer
wrote: I don't know what all that means exactly (especially since GHC's demand signatures have changed recently in a way I don't understand at all). But for hiding divergence, one option is to use a module with demand analysis disabled. Try {-# options_ghc -fno-strictness #-}. You'll likely need to put oops in its own module to avoid interfering with desired optimizations.
THanks for the suggestion!
So I did this:
{-# options_ghc -fno-strictness #-} module ConCat.Oops(oops) where
import GHC.Stack (errorWithStackTrace) -- for oops
-- | Pseudo function to fool GHC's divergence checker. oops :: String -> b oops str = errorWithStackTrace ("Oops: "++str) {-# NOINLINE oops #-}
... but am getting the same result from the divergence checker, sadly ...
-- Regards, Mike
participants (2)
-
David Feuer
-
Michael Sperber