Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cabal build works, but cabal repl has an error. #7696

Open
kindaro opened this issue Oct 1, 2021 · 25 comments
Open

cabal build works, but cabal repl has an error. #7696

kindaro opened this issue Oct 1, 2021 · 25 comments
Labels
cabal-install: cmd/repl can-workaround There is a (maybe partial) workaround for the issue or missing feature status: consider closing

Comments

@kindaro
Copy link

kindaro commented Oct 1, 2021

Describe the bug

I want to do something with QuickCheck. I cloned the current version from the repository. I see a strange problem: cabal build works, but cabal repl has an error when compiling Test.QuickCheck.All. This problem appears both with GHC 8.10.7 and 9.0.1.

See details…
% cabal clean
% cabal build
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- QuickCheck-2.14.2 (lib) (first run)
Configuring library for QuickCheck-2.14.2..
Preprocessing library for QuickCheck-2.14.2..
Building library for QuickCheck-2.14.2..
[ 1 of 16] Compiling Test.QuickCheck.Exception ( src/Test/QuickCheck/Exception.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Exception.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Exception.dyn_o )
[ 2 of 16] Compiling Test.QuickCheck.Random ( src/Test/QuickCheck/Random.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Random.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Random.dyn_o )
[ 3 of 16] Compiling Test.QuickCheck.Gen ( src/Test/QuickCheck/Gen.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Gen.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Gen.dyn_o )
[ 4 of 16] Compiling Test.QuickCheck.Gen.Unsafe ( src/Test/QuickCheck/Gen/Unsafe.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Gen/Unsafe.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Gen/Unsafe.dyn_o )
[ 5 of 16] Compiling Test.QuickCheck.Arbitrary ( src/Test/QuickCheck/Arbitrary.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Arbitrary.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Arbitrary.dyn_o )
[ 6 of 16] Compiling Test.QuickCheck.Poly ( src/Test/QuickCheck/Poly.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Poly.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Poly.dyn_o )
[ 7 of 16] Compiling Test.QuickCheck.Modifiers ( src/Test/QuickCheck/Modifiers.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Modifiers.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Modifiers.dyn_o )
[ 8 of 16] Compiling Test.QuickCheck.Function ( src/Test/QuickCheck/Function.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Function.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Function.dyn_o )
[ 9 of 16] Compiling Test.QuickCheck.Text ( src/Test/QuickCheck/Text.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Text.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Text.dyn_o )
[10 of 16] Compiling Test.QuickCheck.State ( src/Test/QuickCheck/State.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/State.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/State.dyn_o )
[11 of 16] Compiling Test.QuickCheck.Property ( src/Test/QuickCheck/Property.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Property.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Property.dyn_o )
[12 of 16] Compiling Test.QuickCheck.Test ( src/Test/QuickCheck/Test.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Test.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Test.dyn_o )
[13 of 16] Compiling Test.QuickCheck.Monadic ( src/Test/QuickCheck/Monadic.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Monadic.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Monadic.dyn_o )
[14 of 16] Compiling Test.QuickCheck.All ( src/Test/QuickCheck/All.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/All.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/All.dyn_o )
[15 of 16] Compiling Test.QuickCheck.Features ( src/Test/QuickCheck/Features.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Features.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck/Features.dyn_o )
[16 of 16] Compiling Test.QuickCheck  ( src/Test/QuickCheck.hs, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck.o, /tmp/quickcheck/dist-newstyle/build/x86_64-linux/ghc-9.0.1/QuickCheck-2.14.2/build/Test/QuickCheck.dyn_o )
% cabal repl
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- QuickCheck-2.14.2 (lib) (ephemeral targets)
Preprocessing library for QuickCheck-2.14.2..
GHCi, version 9.0.1: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
[ 1 of 16] Compiling Test.QuickCheck.Exception ( src/Test/QuickCheck/Exception.hs, interpreted )
[ 2 of 16] Compiling Test.QuickCheck.Random ( src/Test/QuickCheck/Random.hs, interpreted )
[ 3 of 16] Compiling Test.QuickCheck.Gen ( src/Test/QuickCheck/Gen.hs, interpreted )
[ 4 of 16] Compiling Test.QuickCheck.Gen.Unsafe ( src/Test/QuickCheck/Gen/Unsafe.hs, interpreted )
[ 5 of 16] Compiling Test.QuickCheck.Arbitrary ( src/Test/QuickCheck/Arbitrary.hs, interpreted )
[ 6 of 16] Compiling Test.QuickCheck.Poly ( src/Test/QuickCheck/Poly.hs, interpreted )
[ 7 of 16] Compiling Test.QuickCheck.Modifiers ( src/Test/QuickCheck/Modifiers.hs, interpreted )
[ 8 of 16] Compiling Test.QuickCheck.Function ( src/Test/QuickCheck/Function.hs, interpreted )
[ 9 of 16] Compiling Test.QuickCheck.Text ( src/Test/QuickCheck/Text.hs, interpreted )
[10 of 16] Compiling Test.QuickCheck.State ( src/Test/QuickCheck/State.hs, interpreted )
[11 of 16] Compiling Test.QuickCheck.Property ( src/Test/QuickCheck/Property.hs, interpreted )
[12 of 16] Compiling Test.QuickCheck.Test ( src/Test/QuickCheck/Test.hs, interpreted )
[13 of 16] Compiling Test.QuickCheck.Monadic ( src/Test/QuickCheck/Monadic.hs, interpreted )
[14 of 16] Compiling Test.QuickCheck.All ( src/Test/QuickCheck/All.hs, interpreted )

src/Test/QuickCheck/All.hs:77:39: error:
    • Couldn't match type ‘a0’ with ‘a’
      Expected: String -> a
        Actual: [Char] -> a0
        because type variable ‘a’ would escape its scope
      This (rigid, skolem) type variable is bound by
        a type expected by the context:
          Error
        at src/Test/QuickCheck/All.hs:77:39-41
    • In the first argument of ‘deconstructType’, namely ‘err’
      In a stmt of a 'do' block:
        (polys, ctx, ty) <- deconstructType err ty0
      In the expression:
        do ty0 <- fmap infoType (reify t)
          let err msg = error $ msg ++ ": " ++ pprint ty0
          (polys, ctx, ty) <- deconstructType err ty0
          case polys of
            [] -> return (expName t)
            _ -> do ...
    • Relevant bindings include
        err :: [Char] -> a0 (bound at src/Test/QuickCheck/All.hs:76:7)
  |
77 |   (polys, ctx, ty) <- deconstructType err ty0
  |                                       ^^^

src/Test/QuickCheck/All.hs:82:31: error:
    • Couldn't match type ‘a0’ with ‘a’
      Expected: String -> a
        Actual: [Char] -> a0
        because type variable ‘a’ would escape its scope
      This (rigid, skolem) type variable is bound by
        a type expected by the context:
          Error
        at src/Test/QuickCheck/All.hs:82:31-33
    • In the first argument of ‘monomorphiseType’, namely ‘err’
      In a stmt of a 'do' block: ty' <- monomorphiseType err integer ty
      In the expression:
        do integer <- [t| Integer |]
          ty' <- monomorphiseType err integer ty
          return (SigE (expName t) ty')
    • Relevant bindings include
        err :: [Char] -> a0 (bound at src/Test/QuickCheck/All.hs:76:7)
  |
82 |       ty' <- monomorphiseType err integer ty
  |                               ^^^
Failed, 13 modules loaded.
λ 
Leaving GHCi.

To Reproduce

Clone the repository of QuickCheck at the commit 7ff70fe. Run cabal repl.

Expected behavior

I expect that all modules compile without error in the repl, since they compile without error when running cabal build.

System information

% cabal --version
cabal-install version 3.6.0.0
compiled using version 3.6.1.0 of the Cabal library
@Mikolaj
Copy link
Member

Mikolaj commented Oct 1, 2021

Thank you for the report. Is it the same with with cabal exec cabal repl or cabal exec ghci or ghci alone or whatever else people use? I wonder if this might be a GHC error.

@kindaro
Copy link
Author

kindaro commented Oct 1, 2021

I am not sure I understand what you want me to do. I can build the package and then run cabal exec ghci — it works alright:

% cabal clean
% cabal build
…
% cabal exec ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
Loaded package environment from /tmp/quickcheck/dist-newstyle/tmp/environment.-385457/.ghc.environment.x86_64-linux-8.10.7
Loaded package environment from /tmp/quickcheck/dist-newstyle/tmp/environment.-385457/.ghc.environment.x86_64-linux-8.10.7
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
λ import Test.QuickCheck
λ import Test.QuickCheck.All
λ 
Leaving GHCi.

@gbaz
Copy link
Collaborator

gbaz commented Oct 1, 2021

I'm willing to bet the custom flags set in ghci.conf cause the code to compile differently.

@jneira
Copy link
Member

jneira commented Oct 1, 2021

Just in case i've tried to reproduce it with cabal-3.4.0.0 and 3.6.0.0 and i was not able to do it. No ghc env files nor ghci.conf one in my side.

@kindaro
Copy link
Author

kindaro commented Oct 2, 2021

Yes, if I remove ~/.ghc/ghci.conf then cabal repl succeeds.

Here is the file.
% cat ~/.ghc/ghci.conf
:set prompt "λ "
:set prompt-cont "> "
:set +m

:set -fdefer-typed-holes
:set -fdiagnostics-color=always
:set -Wpartial-type-signatures

:set -XUnicodeSyntax
:set -XBlockArguments
:set -XTypeApplications
:set -XPartialTypeSignatures
:set -XFlexibleInstances
:set -XFlexibleContexts
:set -XMultiParamTypeClasses
:set -XFunctionalDependencies
:set -XRankNTypes
:set -XDataKinds
:set -XKindSignatures
:set -XTypeOperators
:set -XTypeFamilies
:set -XTypeFamilyDependencies
:set -XImportQualifiedPost
:set -XTupleSections

Should I always do cabal build && cabal exec ghci from now on? I like my ghci.conf and I should like to keep it. Or I could write a wrapper for Cabal that carefully stashes ghci.conf in a pocket before calling Cabal and puts it back it after Cabal is done.

@jneira
Copy link
Member

jneira commented Feb 16, 2022

Afaiu cabal repl fail due to some of the language extensions set in ghci.conf. So if you could invoke ghci on that package without cabal (via a global packagedb or ghc environment files) it would fail in the same way. Is that the case?
If it is so, what could do cabal to avoid that error?

@kindaro
Copy link
Author

kindaro commented Feb 17, 2022

  1. Yes, axually I can do this:

    % cabal exec sh
    sh-5.1$ ghci src/Test/QuickCheck/All.hs
    

    — And see the same compilation error.

  2. Maybe some of:

    1. Cabal could make it easy for me to run cabal repl from anywhere with my favourite set of language extensions. Maybe Separate cabal install --lib into own command (cabal env) #6481 can address this problem. Then I could remove ~/.ghc/ghci.conf and instead call cabal repl, so that Cabal reads default extensions from the default cabal manifest and gives them to ghci.
    2. Cabal could ask GHC to ignore ~/ghc/ghci.conf, and GHC could coöperate.
    3. Cabal could override all GHC extension flags to their default state when running ghci.

@jneira
Copy link
Member

jneira commented Feb 18, 2022

Thanks for the confirmation and the proposals

Cabal could make it easy for me to run cabal repl from anywhere with my favourite set of language extensions. Maybe #6481 can address this problem. Then I could remove ~/.ghc/ghci.conf and instead call cabal repl, so that Cabal reads default extensions from the default cabal manifest and gives them to ghci.

But your favourite set of language extensions are the ones in the ghci.conf and those made the load fail for that package, no?
So that list of extension would made fail cabal if it picks them from other source. Otoh you can have other ghci configuration (prompt and other things) which would be good to keep.

Cabal could ask GHC to ignore ~/ghc/ghci.conf, and GHC could coöperate.
Cabal could override all GHC extension flags to their default state when running ghci.

Those ones will drive to unexpected behaviour and break actual workflows for users relying in ~/.ghc/ghci.conf

Possible solution:

@kindaro
Copy link
Author

kindaro commented Feb 18, 2022

Thanks for the confirmation and the proposals

At your service!

But your favourite set of language extensions are the ones in the ghci.conf and those made the load fail for that package, no?

Yes, but I only need my favourite language extensions to be present in ~/.ghc/ghci.conf when running ghci outside of any package. If instead I could run cabal repl with a default package, my favourite language extensions would live in that package's cabal manifest. So, there is no problem: I should have my extensions when outside of any package, and the relevant package's extensions when inside a project.

So that list of extension would made fail cabal if it picks them from other source. Otoh you can have other ghci configuration (prompt and other things) which would be good to keep.

  • Currently:

    • When I run cabal repl outside of any project, I get the set of extensions defined in ~/.ghc/ghci.conf.
    • When I run cabal repl in a project, I get the set of extensions defined in ~/.ghc/ghci.conf and the set of extensions defined in the relevant cabal manifest.
  • Ideally:

    • When I run cabal repl outside of any project, I get the set of extensions defined in the default cabal manifest.
    • When I run cabal repl in a project, I get the set of extensions defined in the relevant cabal manifest.

So, what I am saying is that ideally only one place should be a source of truth as regards language extensions. Then there could be no mistake.

Cabal could ask GHC to ignore ~/ghc/ghci.conf, and GHC could coöperate.
Cabal could override all GHC extension flags to their default state when running ghci.

Those ones will drive to unexpected behaviour and break actual workflows for users relying in ~/.ghc/ghci.conf

Cabal already has unexpected behaviour and breaks actual workflows for users relying in ~/.ghc/ghci.conf. (Me for example.) You have to be honest here and say either that:

  • Cabal promised from the outset to support arbitrary ~/.ghc/ghci.conf. Then Cabal is already breaking its promise to me.
  • Cabal never promised to support arbitrary ~/.ghc/ghci.conf. Then Cabal can choose any behaviour without breaking any promises.

Possible solution:

Sure, I can solve this problem for this specific case one way or another. I can figure out which language extension is causing this version of GHC to decline this version of QuickCheck, and disable that specific extension.

@phadej
Copy link
Collaborator

phadej commented Feb 18, 2022

@kindaro use :seti, don't use :set.

@kindaro
Copy link
Author

kindaro commented Feb 18, 2022

@phadej   Thank you Oleg for your thoughtful advice.

Unfortunately, my workflows rely on there being :set and not :seti. For example:

% cat X.hs
main ∷ IO ( )
main = putStrLn "Hello world"
% ghci X.hs
GHCi, version 9.0.2: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
[1 of 1] Compiling Main             ( X.hs, interpreted )
Ok, one module loaded.
λ 

— This relies on the extension UnicodeSyntax being enabled during compilation (note the Unicode symbol in the type signature), which rules out :seti. Similarly for other extensions I want to have enabled by default.

Aside from that, I should note that your response carries the air of talking down to me and dismissing my problem. You can greatly increase my willingness to report issues I might have with Cabal in the future by acknowledging the problem and framing your advice as an advice and not as a dismissive order.

@phadej
Copy link
Collaborator

phadej commented Feb 18, 2022

Then, I'm afraid, you cannot have your cake and eat it too. Settings set with :set -XFoo affect how GHC interprets modules, and Cabal has no means to tell GHC to load some modules without .ghci commands effects (*and subsequent :reloads), i.e. just using what .cabal file prescribes, and then tell GHCi to interpret .ghci.

The only thing Cabal could do, is to tell GHC to completely ignore .ghci file, I think you won't like that either.

@jneira jneira added can-workaround There is a (maybe partial) workaround for the issue or missing feature and removed type: user-question labels Feb 18, 2022
@jneira
Copy link
Member

jneira commented Feb 18, 2022

Cabal promised from the outset to support arbitrary ~/.ghc/ghci.conf. Then Cabal is already breaking its promise to me.

It breaks its promises adding its language extensions to ghci.conf ones? or in other ways?

Cabal never promised to support arbitrary ~/.ghc/ghci.conf. Then Cabal can choose any behaviour without breaking any promises.

The only thing Cabal could do, is to tell GHC to completely ignore .ghci file, I think you won't like that either

Those are compatible but it will break lot of things out there so it should be guarded by a flag or something

What about set --ghc-options="-ignore-dot-ghci"?, not sure if that will work but you could set that in your global,project or package config

So, what I am saying is that ideally only one place should be a source of truth as regards language extensions. Then there could be no mistake.

That is an interesting argument, I guess it should apply to everything in which config.ghci and cabal could collide

@kindaro
Copy link
Author

kindaro commented Feb 18, 2022

Cabal promised from the outset to support arbitrary ~/.ghc/ghci.conf. Then Cabal is already breaking its promise to me.

It breaks its promises adding its language extensions to ghci.conf ones? or in other ways?

If Cabal promises that its commands will work across installations (including modules being both compiled and interpreted) then its commands should work (and fail) uniformly across installations. For example, if Nick can load some modules in the read-evaluate-print loop, then Ignat should be able to do it too, given that they run from within the two clones of the same package and with the same version of GHC.

So, if Cabal promises that, then Cabal should take care of the possibility that ~/.ghc/ghci.conf sets some language extensions that are usually harmless but have adverse effect in a few edge cases. If, on the other hand, Cabal does not promise that, then Cabal is free to take care of this possibility. In any case, Cabal is not forbidden to take care of this possibility.


Then, I'm afraid, you cannot have your cake and eat it too. Settings set with :set -XFoo affect how GHC interprets modules, and Cabal has no means to tell GHC to load some modules without .ghci commands effects (*and subsequent :reloads), i.e. just using what .cabal file prescribes, and then tell GHCi to interpret .ghci.

The only thing Cabal could do, is to tell GHC to completely ignore .ghci file, I think you won't like that either.

But Cabal has the means to tell GHC to load arbitrary scripts. For example, it can ask GHC to load a script that resets all language extensions to their default state. Even if there was no special flag for this case (and there is — -ghci-script), Cabal has control over the standard input of the ghci process — it can do anything. Even if that was not the case, we could ask the GHC people to add a feature to this end. Surely it is not a problem in principle to tell GHC which extensions to enable and which to disable!

@phadej
Copy link
Collaborator

phadej commented Feb 19, 2022

For example, it can ask GHC to load a script that resets all language extensions to their default state.

How? AFAIK that is not possible. (Please link to GHC documentation. or give an explicit example). Note that Cabal invokes ghci as a single command, and doesn't "execute" any command inside the repl.

@bacchanalia
Copy link
Collaborator

cabal already passes a script to ghci when invoking cabal repl outside of project context to set the working directory properly because of the fake-package machinery, so that capability definitely exists

@kindaro
Copy link
Author

kindaro commented Feb 20, 2022

For example, it can ask GHC to load a script that resets all language extensions to their default state.

How? AFAIK that is not possible. (Please link to GHC documentation. or give an explicit example).

Here is an example where I reset UnicodeSyntax to default:

(Recall that I have UnicodeSyntax enabled in ~/.ghc/ghci.conf.)

% cat X.hs
main ∷ IO ( )
main = putStrLn "Hello world"
% cat reset.ghci
:set -XNoUnicodeSyntax
% ghci X.hs
GHCi, version 9.0.2: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
[1 of 1] Compiling Main             ( X.hs, interpreted ) [flags changed]
Ok, one module loaded.
λ 
Leaving GHCi.
% ghci -ghci-script reset.ghci X.hs
GHCi, version 9.0.2: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
Loaded GHCi configuration from reset.ghci
[1 of 1] Compiling Main             ( X.hs, interpreted ) [flags changed]

X.hs:1:1: error:
    Parse error: module header, import declaration
    or top-level declaration expected.
  |
1 | main ∷ IO ( )
  | ^^^^^^^^^^^^^
Failed, no modules loaded.
λ 
Leaving GHCi.

Now it is only a matter of preparing the scripts.

Note that Cabal invokes ghci as a single command, and doesn't "execute" any command inside the repl.

Is there something to stop me from making it do that? I can even do it from the command line:

% ghci <<EOF
heredoc> :set -XNoUnicodeSyntax
heredoc> :load X
heredoc> EOF
GHCi, version 9.0.2: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/kindaro/code/dotfiles/ghci.conf
λ λ [1 of 1] Compiling Main             ( X.hs, interpreted ) [flags changed]

X.hs:1:1: error:
    Parse error: module header, import declaration
    or top-level declaration expected.
  |
1 | main ∷ IO ( )
  | ^^^^^^^^^^^^^
Failed, no modules loaded.
λ Leaving GHCi.

What is going on?

Oleg, I get that you have a lot of experience hacking on Cabal. But I do not understand what you are trying to say. It is hard for me to believe that you find it hard to implement a solution to this issue. Surely it is easy for you.

  • Is your message that we should leave this issue be?
  • Do you foresee some forbidding problems that may arise in the future if we solve this issue?
  • If such a tiny problem cannot be solved easily, then maybe some code in the Cabal code base needs to be refactored?
  • Maybe there are some conceptual problems with the way Cabal handles GHC executables? 

What is making you so grim?

@phadej
Copy link
Collaborator

phadej commented Feb 20, 2022

cabal already passes a script to ghci when invoking cabal repl outside of project context to set the working directory properly because of the fake-package machinery, so that capability definitely exists

That script is (AFAIK) executed after ~/ghc/ghci.conf is loaded, and therefore if we e.g. do something like -XNoTypeApplications it:

    1. will unset it for the repl,. i.e. foo @Bar won't work in repl anymore: users will be surprised
    1. If .cabal file in fact has default-extensions: TypeApplications, such reset will potentially make package fail to load.

It is hard for me to believe that you find it hard to implement a solution to this issue.

This is not an issue which we should hack around in Cabal. GHC should provide the means to do it, but I don't see how it can be done now.

@phadej
Copy link
Collaborator

phadej commented Feb 20, 2022

If such a tiny problem cannot be solved easily, then maybe some code in the Cabal code base needs to be refactored?

I try to say it should be "fixed" in GHC, to allow module loading before .ghci.conf is applied. (And somehow that should make :reload work too). This is a feature request to GHC, not a bug in Cabal.

@jneira
Copy link
Member

jneira commented Feb 20, 2022

Agree with the analysis, i would try to not coupling even more cabal and ghc(i). How could we implement the solution without hardcoding ghci specific knowledge in cabal?

Imo the cabal repl script use of a ghci script was a hack on top of another hack (fake-package), and recognized as such. It was needed to implement a miss for too long feature with complicated workarounds.

@phadej
Copy link
Collaborator

phadej commented Feb 20, 2022

Imo the cabal repl script use of a ghci script was a hack on top of another hack (fake-package), and recognized as such. It was needed to implement a miss for too long feature with complicated workarounds.

Fortunately these "hacks" would naturally decouple&vanish when fake-package hack is removed. If cabal-install would be able to create a package environment directly, then the invocation of ghci with that environment in correct working directory will be a lot easier.

Sometimes to make progress you need to take step back.

However, reimplementing of package environment creation is not related to this issue: in project context there is no need to fake package, as there is a project where everything is happening. (I don't know how ghci.conf could break out-of-package cabal repl, as there we don't ask ghci to interpret anything).

@phadej
Copy link
Collaborator

phadej commented Feb 20, 2022

a side note: ghci will gain a multi-home-package functionality, but then :set won't even work initially. The problem is very similar to what's happening there, as far as i understand: different packages have different dynflags and it's all somewhat complicated. :seti however works already.

See https://gitlab.haskell.org/ghc/ghc/-/issues/20889

it summarizes this problem well:

The interface for GHCi heavily assumes that there is only one home unit in a session.

(and :set etc. stuff @kindaro wants to work should not apply that only home unit!)

@jneira
Copy link
Member

jneira commented Jun 4, 2022

Somewhat related; #4572

@ulysses4ever
Copy link
Collaborator

ulysses4ever commented Jul 23, 2022

The root cause here is whether it's a good idea to load ~/.ghci by default, which is the subject of #1471. Also, #7789 is somewhat related. Perhaps, either Cabal or GHC in their output should be more explicit about the fact of loading the user config and possible consequences.

@ulysses4ever
Copy link
Collaborator

No activity here and there's some related work in other tickets linked above. I propose closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cabal-install: cmd/repl can-workaround There is a (maybe partial) workaround for the issue or missing feature status: consider closing
Projects
None yet
Development

No branches or pull requests

7 participants