Build LH with GHC 9.4.7
facundominguez opened this issue · comments
Continuing the epic #2184, I'm trying now to build LH with GHC 9.4.7. I have some work in progress in this branch.
liquidhaskell
builds, but then trying to build liquid-prelude
fails. See the details in a follow up comment. I expect a few more issues that are yet undiscovered to come.
thanks @facundominguez !!!
Building a few modules from liquid-prelude fails with the following panic:
$ cabal build -fdevel liquid-prelude
...
<no location info>: error:
panic! (the 'impossible' happened)
GHC version 9.4.7:
lookupIdSubst
empty
InScope {k_a1sK $dOrd_a1sL ds_d2f6
lq_anf$##7205759403792802262_d2fI fromList}
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/GHC/Utils/Panic.hs:182:37 in ghc:GHC.Utils.Panic
pprPanic, called at compiler/GHC/Core/Subst.hs:260:17 in ghc:GHC.Core.Subst
Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
The complete trace is as follows:
Plugin.hs
calls to liquidQuery
, which calls to updTargetInfoTermVars
, which calls to terminationVars
, which calls to failingBinds
, which calls to checkBind
, which calls to deShadowBind
, which calls to deShadowBinds, which calls to substBind
, which calls to substExpr
, which calls to lookupIdSubst, which panics.
Maybe LH is calling deShadowBinds
to rename local variables. But I don't understand exactly why yet. Maybe someone on the LH side can fill in this context.
On the other hand, deShadowBinds
is an internal function in GHC that is currently dead code in GHC. So I have no explicit advice on how to call it. Though I would conjecture that the bindings that the assertion reports as missing need to be provided all in one single call to deShadowBinds
. This might not have been a problem before because lookupIdSubst
didn't use to panic in ghc-9.2
, the panic
call is new in ghc-9.4
.
In the absence of other insights, I'm eliminating the call to deShadowBinds
and will see what fails.
Almost there. I have only one testsuite failing: benchmark-vector-algorithms
So far, I haven't encountered any consequences of removing the call to deShadowBinds
.
This error seems to be due to the introduction of coercions in the desugaring of
{-@ countLoop :: (v (PrimState m) e)
-> count:(PV.MVector (PrimState m) Int)
-> (e -> (OkIdx count)) -> m ()
@-}
countLoop :: (PrimMonad m, MVector v e)
=> (v (PrimState m) e) -> (PV.MVector (PrimState m) Int)
-> (e -> Int) -> m ()
countLoop src count rdx = set count 0 >> go len 0
where
len = length src
go (m :: Int) i
| i < len = let lenSrc = length src
in (unsafeRead src i) >>= inc count . rdx >> go (m-1) (i+1)
| otherwise = return ()
The error says:
tests/benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Common.hs:80:36: error:
Liquid Type Mismatch
.
The inferred type
VV : {v : GHC.Types.Int | v == i
&& v + ?b == vsize src
&& v >= 0
&& 0 <= v
&& v <= vsize src}
.
is not a subtype of the required type
VV : {VV : GHC.Types.Int | VV <= vsize (coerce (v##a1sH s##a1sJ e##a1sI) ~ (v##a1sH (Control.Monad.Primitive.PrimState m##a1tq) e##a1sI) in src) - (0 + 1)}
.
in the context
src : a b c
i : {i : GHC.Types.Int | i + ?b == vsize src
&& i >= 0
&& 0 <= i
&& i <= vsize src}
?b : {?b : GHC.Types.Int | ?b >= 0
&& 0 <= ?b
&& ?b <= vsize src}
Constraint id 44
|
80 | in unsafeRead src i >>= inc count . rdx >> go (m-1) (i+1)
| ^
And examining the Core does indeed show that ghc-9.4 introduces a cast around the first argument of unsafeRead
:
unsafeRead
@m_a1sY
@v_a1sd
@e_a1se
$dPrimMonad_a1u5
$dMVector_a1sg
((src<tests/benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Common.hs:80:33-35>
src_a1qn)
`cast` (<v_a1sd>_R (Sym co_a1uL) <e_a1se>_N
:: v_a1sd (PrimState m_a1sc) e_a1se
~R# v_a1sd (PrimState m_a1sY) e_a1se))
(src<tests/benchmarks/vector-algorithms-0.5.4.2/Data/Vector/Algorithms/Common.hs:80:37>
i_a1qt))
I don't know how to fix this yet.
Apparently the coercion in ghc-9.4 is necessary because go
doesn't have a type signature, and ghc is generalizing the type of go
. Thus, a coercion is needed to say that the m
type variable of countLoop
is instantiated the same as the universally quantified m
type variable of go
.
Disabling let generalization with {-# LANGUAGE MonoLocalBinds #-}
has the module pass verification.
Another fix is to pass src
and count
as parameters of go
, which also prevents the variable m
from being generalized.
I think taming the desugared Core and the inferred type for go
with MonoLocalBinds
is worth the trouble. However, then we need the user to be aware of the problem for her to be able to use LH.
Maybe you have a different plan to ignore the cast that I’m not following?
Not really. I discarded the idea after writing my suggestion. :)
All tests are passing for me now.
Btw just to be clear we could also just add a type signature for go, Yes?
Indeed. A type signature together with ScopedTypeVariables
does also avoid the coercion.