[GHC] #15286: "Can't use Natural in base" when compiling GHC.Natural with -O0
GHC
ghc-devs at haskell.org
Thu Feb 7 13:04:05 UTC 2019
#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0
-------------------------------------+-------------------------------------
Reporter: alpmestan | Owner: (none)
Type: bug | Status: patch
Priority: normal | Milestone:
Component: libraries/base | Version: 8.5
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Building GHC | Unknown/Multiple
failed | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D4880
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by hsyl20):
The current handling of "wired-in" things such as Integer or Natural is
very fragile. In your case, as you use type-level nats, GHC implicitly
needs `Natural` from `GHC.Natural` but it can't access it because
`GHC.Natural` is also defined in `base`. In `coreSyn/CorePrep.hs` we
explicitly detect use of Natural when we compile `base` (see
`guardNaturalUse`) to generate the panic you get. Otherwise GHC would fail
with something like a "can't find/load interface" error.
Not allowing to depend on `Natural` in `base` is annoying/stupid. In the
past I've tried the most obvious solution: put `GHC.Natural` in its own
package just like we do for `integer-*`. However it's harder for Natural
than it is for Integer because `GHC.Natural` uses `Exception` (with an
import cycle) and `Maybe` which are defined in `base`...
I have written a note to state the problem and some ideas:
{{{
GHC has some built-in functions, types, constructors, etc.. These are not
defined in Haskell and when it encounters them it knows what to do with
them.
GHC also knows some Haskell defined functions, types, constructors, etc.
It can
use this knowledge to perform code transformation (e.g. constant folding)
and to
generate some code (e.g. desugaring lists, deriving instances, etc.).
In this latter case, GHC has to build the Haskell code defining these
functions,
types, constructors, etc. without assuming knowledge of non already built
Haskell code. For instance, suppose `Integer` data type and functions are
defined in the "GHC.Integer" module. When building "GHC.Integer" GHC must
assume
that it knows nothing about Integer (nor about anything that depends on
knowing
Integer).
It can be tricky: suppose we are building the Dummy module defined as
follow:
{-# LANGUAGE NoImplicitPrelude #-}
module Dummy where
dummy = 0
Even if Dummy doesn't depend on anything, GHC will default the type of
"dummy"
to Integer! So when building this module, there is an implicit dependency
on
knowing Integer and GHC.Integer must have been built already for GHC to
query
some stuff from it. In this case we could change the default or fix the
type to
avoid the dependency or to make it explicit:
{-# LANGUAGE NoImplicitPrelude #-}
module Dummy where
default (Int)
-- or: dummy :: Int
-- or: import GHC.Integer ()
dummy = 0
At the time of writing, these dependencies are manually handled this way
(in
base, etc.) This is very fragile (see #15286).
-------------
Ideas:
1) we should automatically detect implicit dependencies: when GHC is about
to
use a builtin Name or Id, it should:
- detect the dependency it comes from
- detect cyclic dependencies with the current module
- ensure the dependency is built
- clearly indicate why it can't build the implicit dependency if it
happens
Shouldn't be too hard: GHC should pretend the module contains an implicit
"import" when it is about to use a builtin. GHC could even "source import"
dependencies when there is a cycle because it would mean we compile the
package
containing both modules.
A minor issue is that this implicit import could appear quite late in the
compilation pipeline (during desugaring, deriving, maybe codegen, etc.):
GHC
could have to switch from building the current module to build the
dependencies
or fail and indicate to the caller the dependencies to build beforehand.
The
latter would be relatively slow because GHC would need to start compiling
the
module again and may fail the same way further in the compilation pipeline
until
all dependencies are built.
2) GHC shouldn't assume knowledge of unit IDs. We should be able to
disable
whole builtin stuff at once.
E.g. when building integer-* packages, GHC uses predefined unit-id with
the
parameter: -this-unit-id integer-wired-in
We should avoid this: instead GHC should query the unit-id of the
integer-*
package somehow (or use one given on the command line to allow easy switch
between integer packages). We should also allow the possibility of
compiling
without integer-* package at all: this is what is implicitly assumed by
GHC when
it builds ghc-prim and integer-* packages (see `guardIntegerUse` in
coreSyn/CorePrep.hs).
Instead of relying on knowing two blessed integer-* packages, GHC could
detect
the presence of constructors such as "S#" in the given integer package so
to use
rules and generate code accordingly. It would make trying new
releases/implementations of those much easier.
Same for other packages (natural, base, template-haskell, etc.). E.g. we
should
be able to disable template-haskell, etc. When some dependencies are
disabled/missing, GHC can't produce code using them nor use builtin rules
assuming it knows them.
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15286#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list