[GHC] #15286: "Can't use Natural in base" when compiling GHC.Natural with -O0

#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0 -------------------------------------+------------------------------------- Reporter: alpmestan | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: | Version: 8.5 libraries/base | Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Building GHC Unknown/Multiple | failed Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- {{{ _build/stage0/bin/ghc -Wall -hisuf hi -osuf o -hcsuf hc -static -hide-all- packages -no-user-package-db '-package-db _build/stage1/lib/package.conf.d' '-this-unit-id base-4.12.0.0' '-package- id ghc-prim-0.5.3' '-package-id integer-simple-0.1.1.1' '-package-id rts-1.0' -i -i_build/stage1/libraries/base/build -i_build/stage1/libraries/base/build/autogen -ilibraries/base/. -Iincludes -I_build/generated -I_build/stage1/libraries/base/build -I_build/stage1/libraries/base/build/include -Ilibraries/base/include -I/home/travis/build/snowleopard/hadrian/ghc/_build/stage1/lib/x86_64 -linux-ghc-8.5.20180617/rts-1.0/include -I_build/generated -optc- I_build/generated -optP-include -optP_build/stage1/libraries/base/build/autogen/cabal_macros.h -optc- std=gnu99 -optc-fno-stack-protector -optP-std=gnu99 -odir _build/stage1/libraries/base/build -hidir _build/stage1/libraries/base/build -stubdir _build/stage1/libraries/base/build -Wnoncanonical-monad-instances -optc- Werror=unused-but-set-variable -optc-Wno-error=inline -c libraries/base/GHC/Num.hs -o _build/stage1/libraries/base/build/GHC/Num.o -O0 -H64m -this-unit-id base -Wcompat -Wnoncanonical-monad-instances -XHaskell2010 -ghcversion- file=/home/travis/build/snowleopard/hadrian/ghc/_build/generated/ghcversion.h -Wno-deprecated-flags -Wno-trustworthy-safe Exit code: 1 Stderr: ghc: panic! (the 'impossible' happened) (GHC version 8.5.20180617 for x86_64-unknown-linux): Can't use Natural in base }}} We noticed this in hadrian land (in [https://github.com/snowleopard/hadrian/issues/499 this PR] and [https://github.com/snowleopard/hadrian/issues/629]), and noticed that this happens: - with 8.4.2 as the boot compiler but not 8.2.2 - with integer-simple as the integer library - only with the quickest flavour (or more generally when we build GHC.Natural with -O0) Some optimisation seems critical to making any trace of `Natural` disappear, but this seems rather fragile. The code that throws the error got introduced in fe770c211631e7b4c9b0b1e88ef9b6046c6585ef. The full build log is available [https://travis- ci.org/snowleopard/hadrian/jobs/393259151#L4209 here], anchored to where the error appears. An example of hadrian command to reproduce the problem, assuming a configured build tree: `hadrian/build.sh --flavour=quickest --integer- simple -j4`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0 -------------------------------------+------------------------------------- Reporter: alpmestan | Owner: (none) Type: bug | Status: new 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): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): If we build the `GHC.Natural` with `-O0 -fno-omit-interface-pragmas` and build `GHC.Num` with `-O0 -fno-ignore-interface-pragmas`, the panic disappears. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0 -------------------------------------+------------------------------------- Reporter: alpmestan | Owner: (none) Type: bug | Status: new 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): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): These two flags are only enabled with `-O0`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0 -------------------------------------+------------------------------------- Reporter: alpmestan | Owner: (none) Type: bug | Status: new 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): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): With `-O0`, if we remove the methods `+` and `-` from the `instance Num Natural` then everything works well. Link: https://git.haskell.org/ghc.git/blob/fe770c211631e7b4c9b0b1e88ef9b6046c6585e... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15286: "Can't use Natural in base" when compiling GHC.Natural with -O0 -------------------------------------+------------------------------------- Reporter: alpmestan | Owner: (none) Type: bug | Status: new 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): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): That is quite helpful. Thanks! -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#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: | -------------------------------------+------------------------------------- Changes (by hsyl20): * status: new => patch * differential: => Phab:D4880 Comment: I can reproduce. I agree that the integration of built-in Natural (and Integer) in GHC is fragile... Maybe we should fully disable Natural built- in rules when we compile `base` to avoid this issue. In the meantime I have implemented your workaround in Phab:D4880 (it also fixes a critical copy-paste bug). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#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 simonpj): Compiling `Num` with `-O0` will kill numeric performance for every single Haskell program -- it's not acceptable. Does anyone understand what the actual problem is here? Why does it only happen with Hadrian? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#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 alpmestan): I haven't looked into the actual problem, but hsyl20's instructions from https://ghc.haskell.org/trac/ghc/ticket/15570#comment:13 seem to work, I just opened [https://github.com/snowleopard/hadrian/pull/674 hadrian#674] to get rid of those `-O0`s. This also fixes many failing tests. This doesn't answer anything about the problem though of course. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#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 rockbmb): As part of ticket #15622 that I opened, I ran into this issue when I introduced an import to `GHC.TypeNats` in `libraries/base/Data/Fixed.hs`, having used it to replace an import to `GHC.TypeLits`. I also added two extensions, `{-# LANGUAGE DataKinds #-}` and `{-# LANGUAGE KindSignatures #-}`, which may be part of the problem. The associated commit is [here](https://gitlab.haskell.org/rockbmb/ghc/commit/c6726d732273785b53986f152a6e03...), and the failure I got in CI was: ``` HC [stage 1] libraries/base/dist-install/build/Data/Fixed.o HC [stage 1] libraries/base/dist-install/build/Data/Complex.o ghc-stage1: panic! (the 'impossible' happened) (GHC version 8.7.20190206 for x86_64-unknown-linux): Can't use Natural in base Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug make[1]: *** [libraries/base/dist-install/build/Data/Fixed.o] Error 1 make[1]: *** Waiting for unfinished jobs.... libraries/base/ghc.mk:4: recipe for target 'libraries/base/dist- install/build/Data/Fixed.o' failed make: *** [all] Error 2 Makefile:123: recipe for target 'all' failed ```. I included the error here because CI build logs in GitLab disappear after 1 week. I hope this helps, and if there's anything I can do to help close this issue I'll be happy to help. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15286#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#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
participants (1)
-
GHC