sol / doctest

An implementation of Python's doctest for Haskell
https://hackage.haskell.org/package/doctest
MIT License
372 stars 72 forks source link

Ambiguous modules #119

Open fizruk opened 8 years ago

fizruk commented 8 years ago

In GetShopTV/swagger2#15 the tests are failing because of an "ambiguous module name" error raised by doctest. The reason seems to be that doctest is looking in the whole stack snapshot instead of looking only for packages specified in .cabal file.

This can be fixed in the package with PackageImports and in that particular case only one import needs that. But still it feels wrong to protect imports that should be okay otherwise.

Is there an option or something to prevent this ambiguity somehow? Or should there be?

bergmark commented 8 years ago

It would definitely be nice to fix this as we'll run across this more and more as the number of packages grow. I've assumed it to be hard although I don't really know :)

Would it work to pass --hide-all-packages to GHC and then passing the packages we want with --package? One way to get the packages we need is to read it from the cabal file (does it have to be an data-file for that or is it always available?)

I'm currently pointing people to https://github.com/bergmark/blog/blob/master/2016/package-faq.md#ambiguous-modules-when-using-doctest which doesn't really contain a solution.

soenkehahn commented 8 years ago

Personally I would much rather see these kinds of problems solved by cabal/stack exec .... Ideally these exec commands would allow to set up an environment (probably through env vars) in which every call to ghc or ghci would Just Work. ghc would see the packages that the project depends on and only these packages. Including all test and benchmark dependencies. And #include cabal_macros.h and import Paths_$PROJECT should also just work.

That way not only doctest would benefit, but other tools as well.

roman commented 6 years ago

I want to emphasize the importance of this issue.

Crux of the issue

Given doctest GHC invocation uses all the packages installed in a machine, if for any reason any developer or CI machine is working in multiple projects with dependencies that share the same module names (e.g. Crypto.Hash), doctest will fail with "ambiguous module references".

Implications

Currently, there are around 400 duplicated modules in the lts-12 snapshot, which is roughly 2% of all the modules in the snapshot, if you happen to work in projects where they use these dependencies, you will have this error, not just that, there is nothing stopping a troll in uploading a package to Hackage that makes all modules ambiguous for that matter.

Using doctest makes your test infrastructure dependant on environmental dependencies, and what combination of projects/branches you are currently working in the same machine.

Possible solutions

The ideal solution

Do something similar to what stack does:

  1. Hides all packages from a database
  2. reads the cabal file of the project and can figure out what are the dependencies that need to use
  3. invokes GHC with the explicit list of dependencies that the code requires.

A "manual" solution

Specify on a config file all the dependencies you want to have in the project, no need to have cabal as a dependency, but (likely) you'll have your dependencies listed in different sources of truth.

Other solutions?

The list above is not exhaustive, feel free to keep adding suggestions around what we can do.

Thanks!

quasicomputational commented 6 years ago

cabal-doctest does this already. It's a hack but there aren't any non-hacky solutions presently, and it has the high virtue of working like a charm right now and the even higher virtue of being easy to rip out once there's a proper solution.

haskell/cabal#4500 is where we've been tossing around some ideas for giving Cabal the smarts to invoke doctest itself with all the necessary information, but it's still on the whiteboard (contributions welcome, of course).

qrilka commented 5 years ago

https://github.com/commercialhaskell/stack/pull/4652 fixes this issue in Stack's master by using properly constructed env variable $GHC_ENVIRONMENT.