
#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