[GHC] #16343: Changing an irrelevant constraint leads to inlining failure
GHC
ghc-devs at haskell.org
Wed Feb 20 10:20:06 UTC 2019
#16343: Changing an irrelevant constraint leads to inlining failure
-------------------------------------+-------------------------------------
Reporter: mpickering | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.6.3
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
This is an example Andres sent me but I can't work out precisely what is
going on.
{{{
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Tests where
import Data.Kind
import Data.Maybe (maybeToList)
data Product (f :: a -> Type) (xs :: [a]) :: Type where
Nil :: Product f '[]
(:*) :: f x -> !(Product f xs) -> Product f (x : xs)
infixr 5 :*
class Top a
instance Top a
class (forall d . (forall x . c x => d x) => All d xs) => All (c :: a ->
Constraint) (xs :: [a]) where
ccataList ::
f '[]
-> (forall y ys . (c y, All c ys) => f ys -> f (y : ys))
-> f xs
instance All c '[] where
ccataList nil _cons = nil
{-# INLINE ccataList #-}
instance (c x, All c xs) => All c (x : xs) where
ccataList nil cons = cons (ccataList @_ @c nil cons)
{-# INLINE ccataList #-}
newtype (f ~> g) x = Lambda { apply :: f x -> g x }
cpureProduct :: forall c xs f . All c xs => (forall x . c x => f x) ->
Product f xs
cpureProduct p =
ccataList @_ @c
Nil
(p :*)
{-# INLINE cpureProduct #-}
newtype Apply f g x = MkApply { unApply :: Product (f ~> g) x -> Product f
x -> Product g x }
capplyProduct :: forall c xs f g . All c xs => Product (f ~> g) xs ->
Product f xs -> Product g xs
capplyProduct =
unApply $
ccataList @_ @c
(MkApply (\ Nil Nil -> Nil))
(\ rec -> MkApply (\ (f :* fs) (x :* xs) -> apply f x :* unApply rec
fs xs))
{-# INLINE capplyProduct #-}
-- The addition of the constraint makes the test pass.
mapProduct :: forall c xs f g . ({- All Top xs, -} All c xs) => (forall x
. c x => f x -> g x) -> Product f xs -> Product g xs
mapProduct p q =
capplyProduct @Top (cpureProduct @c (Lambda p)) q
{-# INLINE mapProduct #-}
test :: Product [] [ (), (), () ]
test =
mapProduct @Top maybeToList (cpureProduct @Top Nothing)
reference :: Product [] [ (), (), () ]
reference =
[] :* [] :* [] :* Nil
}}}
`test` should simplify to something close to `reference.
There are a few ways to make it do so.
1. Uncomment the constraint in `mapProduct`
2. Change `Top` to `c` in `capplyProduct @Top`.
From looking at `-ddump-inlinings`, it seems that things start to go wrong
when `$cccataList` is inlined.
In the good case, it looks like this.
{{{
Considering inlining: $cccataList_a1Bi
arg infos [ValueArg, ValueArg, ValueArg, ValueArg, NonTrivArg,
NonTrivArg]
interesting continuation RhsCtxt
some_benefit True
is exp: True
is work-free: True
guidance ALWAYS_IF(arity=4,unsat_ok=False,boring_ok=False)
ANSWER = YES
}}}
In the bad case it looks like
{{{
Considering inlining: $cccataList_a1Bv
arg infos [ValueArg, ValueArg, ValueArg, ValueArg]
interesting continuation RuleArgCtxt
some_benefit True
is exp: True
is work-free: True
guidance ALWAYS_IF(arity=4,unsat_ok=False,boring_ok=False)
ANSWER = YES
}}}
Notice the continuation and arg infos are different for the two cases. The
first case seems to be eta expanded?
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16343>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list