[GHC] #14231: Core lint error "in result of Static argument"
GHC
ghc-devs at haskell.org
Tue Jul 10 22:48:58 UTC 2018
#14231: Core lint error "in result of Static argument"
-------------------------------------+-------------------------------------
Reporter: mpickering | Owner: (none)
Type: bug | Status: patch
Priority: normal | Milestone:
Component: Compiler | Version: 8.5
Resolution: | Keywords:
| StaticArgumentTransformation
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D4945
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
Aargh. I'm an idiot. My claim that cloning is unnecessary is
utterly wrong. Here's a fixed version of the latter part of comment:13.
We want to generate this:
{{{
f :: forall a b. (a,b) -> b -> Int
f = /\a b. \(x:(a,b)) (y:b).
letrec fwrk = /\a \(x:(a,b).
REPLACE (f <ty> b <e> y) WITH (fwrk <ty> <e>)
IN <body>
in fwrk a x
}}}
Here `fwrk` is the local, recursive worker, which has free variables `b`'
and `y::b`.
Notice that the binders of `fwrk`, namely `a` and `x::(a,b)` must be
identical (same
unique) as the originals, because they are mentioned in `<body>`.
What is this "REPLACE" business? We want to replace a recusive call to
`f` with
a call to `fwrk`. The easy way to do this is with a non-recursive let,
later inlined:
{{{
f = /\a b. \(x:(a,b)) (y:b).
letrec fwrk :: forall a. (a,b) -> Int
fwrk = /\a \(x:(a,b).
let f :: forall a b1. (a,b) -> b -> Int
f = /\a _ \(x::(a,b) (_::b). fwrk a x
in <body>
in fwrk a x
}}}
We must use the ''same'' unique for that inner `f`:
we are deliberately shadowing its outer binding.
Notice too that I used underscores (i.e. freshly-cloned variables that are
never
referred to) for the static variables. Reason: `fwrk t` expects an
argument of type
`(t,b)`, where `b` scopes globally over the entire definition of `fwrk`.
We ''cannot''
write
{{{
let f :: forall a b. (a,b) -> b -> Int
f = /\a b \(x::(a,b) (y::b). fwrk a x
}}}
becuase then the call to `fwrk` is ill-typed.
This is what `Note [Binder type capture]` is about. We should clone the
static binders; and it does no harm to clone everything I suppose.
------------------
So what is wrong in commnet:8. Here's the actual error message
{{{
In the expression: bindWith @ a_a17R k_atm f_atn
Mismatch in type between binder and occurrence
Var: bindWith_rqJ
Binder type: forall a. (a_a17R -> a_a17R) -> a_a17R -> a_a17R
Occurrence type: forall a. (a -> a) -> a -> a
Before subst: forall a. (a -> a) -> a -> a
}}}
Ah! Indeed in our running example, the REPLACE binding for `f` has type
{{{
let f :: forall a b1. (a,b) -> b -> Int
f = /\a _ \(x::(a,b) (_::b). fwrk a x
}}}
and indeed that is not the type of the top-level `f`. But each
''occurrence'' of `f` has the top of the top-level `f` and Lint is
objecting that there seems to be an inconsistency. If we just let
it inline, everything would be fine.
How tiresome. Using a let-binding to do the REPLACE stuff is not as
convenient as it seems :-(.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14231#comment:15>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list