[GHC] #11176: Typechecked AST for recursive top-level call refers to non-exported HsVar.
GHC
ghc-devs at haskell.org
Tue Dec 8 12:31:18 UTC 2015
#11176: Typechecked AST for recursive top-level call refers to non-exported HsVar.
-------------------------------------+-------------------------------------
Reporter: literon | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
I'm surprised that `n_sort` is `WiredIn` for `aaa`. That is most
peculiar.
Did you read `Note [AbsBinds]` in `HsBinds`?
{{{
Note [AbsBinds]
~~~~~~~~~~~~~~~
The AbsBinds constructor is used in the output of the type checker, to
record
*typechecked* and *generalised* bindings. Consider a module M, with this
top-level binding
M.reverse [] = []
M.reverse (x:xs) = M.reverse xs ++ [x]
In Hindley-Milner, a recursive binding is typechecked with the *recursive*
uses
being *monomorphic*. So after typechecking *and* desugaring we will get
something
like this
M.reverse :: forall a. [a] -> [a]
= /\a. letrec
reverse :: [a] -> [a] = \xs -> case xs of
[] -> []
(x:xs) -> reverse xs ++
[x]
in reverse
Notice that 'M.reverse' is polymorphic as expected, but there is a local
definition for plain 'reverse' which is *monomorphic*. The type variable
'a' scopes over the entire letrec.
That's after desugaring. What about after type checking but before
desugaring?
That's where AbsBinds comes in. It looks like this:
AbsBinds { abs_tvs = [a]
, abs_exports = [ABE { abe_poly = M.reverse :: forall a. [a]
-> [a],
, abe_mono = reverse :: [a] -> [a]}]
, abs_binds = { reverse :: [a] -> [a]
= \xs -> case xs of
[] -> []
(x:xs) -> reverse xs ++ [x] }
}
Here,
* abs_tvs says what type variables are abstracted over the binding
group,
just 'a' in this case.
* abs_binds is the *monomorphic* bindings of the group
* abs_exports describes how to get the polymorphic Id 'M.reverse' from
the
monomorphic one 'reverse'
Notice that the *original* function (the polymorphic one you thought
you were defining) appears in the abe_poly field of the
abs_exports. The bindings in abs_binds are for fresh, local, Ids with
a *monomorphic* Id.
If there is a group of mutually recursive functions without type
signatures, we get one AbsBinds with the monomorphic versions of the
bindings in abs_binds, and one element of abe_exports for each
variable bound in the mutually recursive group. This is true even for
pattern bindings. Example:
(f,g) = (\x -> x, f)
After type checking we get
AbsBinds { abs_tvs = [a]
, abs_exports = [ ABE { abe_poly = M.f :: forall a. a -> a
, abe_mono = f :: a -> a }
, ABE { abe_poly = M.g :: forall a. a -> a
, abe_mono = g :: a -> a }]
, abs_binds = { (f,g) = (\x -> x, f) }
}}}
If it's not clear enough I should rewrite it until it is.
So yes, there's a fundamental reason.
The rule is this: a reference on the RHS goes to the monomorphic version
(`abe_mono`) iff
* The variable, say 'x', has no type signature
* The RHS is part of a mutually recursive group which binds 'x'.
To find mutually recursive groups, perform a strongly-connnected-component
analysis on the bindings, where there is a an edge from binding `y = ey`
to `x = ex` iff
* `ey` mentions `x`
* `x` does not have a type signature
Does that help? How could the Note be better?
Simon
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11176#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list