[Git][ghc/ghc][master] Fix arity type of coerced types in CoreArity
Marge Bot
gitlab at gitlab.haskell.org
Fri May 31 06:00:44 UTC 2019
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
bb929009 by Ömer Sinan Ağacan at 2019-05-31T06:00:40Z
Fix arity type of coerced types in CoreArity
Previously if we had
f |> co
where `f` had arity type `ABot N` and `co` had arity M and M < N,
`arityType` would return `ABot M` which is wrong, because `f` is only
known to diverge when applied to `N` args, as described in Note
[ArityType]:
If at = ABot n, then (f x1..xn) definitely diverges. Partial
applications to fewer than n args may *or may not* diverge.
This caused incorrect eta expansion in the simplifier, causing #16066.
We now return `ATop M` for the same expression so the simplifier can't
assume partial applications of `f |> co` is divergent.
A regression test T16066 is also added.
- - - - -
4 changed files:
- compiler/coreSyn/CoreArity.hs
- + testsuite/tests/simplCore/should_run/T16066.hs
- + testsuite/tests/simplCore/should_run/T16066.stderr
- testsuite/tests/simplCore/should_run/all.T
Changes:
=====================================
compiler/coreSyn/CoreArity.hs
=====================================
@@ -11,7 +11,7 @@
-- | Arity and eta expansion
module CoreArity (
manifestArity, joinRhsArity, exprArity, typeArity,
- exprEtaExpandArity, findRhsArity, CheapFun, etaExpand,
+ exprEtaExpandArity, findRhsArity, etaExpand,
etaExpandToJoinPoint, etaExpandToJoinPointRule,
exprBotStrictness_maybe
) where
@@ -702,6 +702,28 @@ lambda wasn't one-shot we don't want to do this.
So we combine the best of the two branches, on the (slightly dodgy)
basis that if we know one branch is one-shot, then they all must be.
+
+Note [Arity trimming]
+~~~~~~~~~~~~~~~~~~~~~
+Consider ((\x y. blah) |> co), where co :: (Int->Int->Int) ~ (Int -> F a) , and
+F is some type family.
+
+Because of Note [exprArity invariant], item (2), we must return with arity at
+most 1, because typeArity (Int -> F a) = 1. So we have to trim the result of
+calling arityType on (\x y. blah). Failing to do so, and hence breaking the
+exprArity invariant, led to #5441.
+
+How to trim? For ATop, it's easy. But we must take great care with ABot.
+Suppose the expression was (\x y. error "urk"), we'll get (ABot 2). We
+absolutely must not trim that to (ABot 1), because that claims that
+((\x y. error "urk") |> co) diverges when given one argument, which it
+absolutely does not. And Bad Things happen if we think something returns bottom
+when it doesn't (#16066).
+
+So, do not reduce the 'n' in (ABot n); rather, switch (conservatively) to ATop.
+
+Historical note: long ago, we unconditionally switched to ATop when we
+encountered a cast, but that is far too conservative: see #5475
-}
---------------------------
@@ -720,7 +742,9 @@ arityType :: ArityEnv -> CoreExpr -> ArityType
arityType env (Cast e co)
= case arityType env e of
ATop os -> ATop (take co_arity os)
- ABot n -> ABot (n `min` co_arity)
+ -- See Note [Arity trimming]
+ ABot n | co_arity < n -> ATop (replicate co_arity noOneShotInfo)
+ | otherwise -> ABot n
where
co_arity = length (typeArity (pSnd (coercionKind co)))
-- See Note [exprArity invariant] (2); must be true of
=====================================
testsuite/tests/simplCore/should_run/T16066.hs
=====================================
@@ -0,0 +1,27 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Main (main) where
+
+import Control.Monad (join)
+import Control.Monad.Reader (ReaderT(..))
+import Control.Concurrent.STM (STM, atomically)
+import Data.Kind (Type)
+
+class Monad (Transaction m) => MonadPersist m where
+ type Transaction m :: Type -> Type
+ atomicTransaction :: Transaction m y -> m y
+
+instance MonadPersist (ReaderT () IO) where
+ type Transaction (ReaderT () IO) = ReaderT () STM
+ atomicTransaction act = ReaderT (atomically . runReaderT act)
+
+main :: IO ()
+main = join (runReaderT doPure2 ()) >>= \x -> seq x (return ())
+
+doPure2 :: MonadPersist m => m (IO ())
+doPure2 = atomicTransaction $ do
+ () <- pure ()
+ () <- pure ()
+ error "exit never happens"
=====================================
testsuite/tests/simplCore/should_run/T16066.stderr
=====================================
@@ -0,0 +1,3 @@
+T16066: exit never happens
+CallStack (from HasCallStack):
+ error, called at T16066.hs:31:3 in main:Main
=====================================
testsuite/tests/simplCore/should_run/all.T
=====================================
@@ -90,3 +90,4 @@ test('T15114', only_ways('optasm'), compile_and_run, [''])
test('T15436', normal, compile_and_run, [''])
test('T15840', normal, compile_and_run, [''])
test('T15840a', normal, compile_and_run, [''])
+test('T16066', exit_code(1), compile_and_run, ['-O1'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/commit/bb929009523a20271e1af34990e5c85d440de0d7
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/commit/bb929009523a20271e1af34990e5c85d440de0d7
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20190531/d3de49bb/attachment-0001.html>
More information about the ghc-commits
mailing list