Ticket #2542 (closed bug: fixed)

Opened 3 months ago

Last modified 2 months ago

runghc does not infer module file extensions

Reported by: judah Assigned to: simonmar
Priority: high Milestone: 6.10.1
Component: Compiler Version: 6.8.3
Severity: normal Keywords:
Cc: Difficulty: Unknown
Test Case: Architecture: Unknown/Multiple
Operating System: Unknown/Multiple

Description

In ghc-6.8 (and possibly earlier), runghc will infer the extension of a module filename if it is not specified at the command line. This feature lets us type, for example, runghc Setup configure without worrying whether there's a Setup.lhs or Setup.hs file present.

For example:

$ cat Useful.hs 
main = putStrLn "Hello, world"
$ runghc Useful
Hello, world

However, this does not work for ghc-6.9.20080824:

$ ~/tmp/ghc-stage/bin/runghc Useful

<no location info>: can't find file: Useful
$ ~/tmp/ghc-stage/bin/runghc Useful.hs
Hello, world

Change History

08/24/08 16:14:59 changed by igloo

  • owner set to igloo.
  • difficulty set to Unknown.

08/24/08 17:24:35 changed by duncan

It's pretty important that this works. We document all over the place that people should use runghc Setup blah.

08/25/08 12:57:46 changed by igloo

  • priority changed from normal to high.
  • milestone set to 6.10.1.

OK, I've (locally) fixed this for filenames like "foo.hs", but for "Setup.hs" (where "Setup" looks like a module name) we get:

$ runghc Setup

Setup.hs:2:7:
    File name does not match module name:
    Saw: `Main'
    Expected: `Setup'

which mirrors

$ ghc --make Setup

Setup.hs:2:7:
    File name does not match module name:
    Saw: `Main'
    Expected: `Setup'

This was a deliberate behaviour change, but I think that it was a mistake. If we really do want this to fail with the above message, then I think ghc --make foo should fail with "Bad module name".

I would prefer that all of these succeed, though, despite the module name not matching the filename. The "ghc --make Setup" and "runhaskell Setup" cases are particularly motivating.

08/26/08 01:07:32 changed by simonmar

Yes, the change was deliberate, but I agree it's not ideal and we should try to fix it. I just don't know what to do about it.

The problem is that people wanted a way to say "load this file with the interpreter only, ignore any compiled code for it". And the solution we adopted for this was to say that any target named by filename (rather than module) would be loaded with the interpreter. But the problem is that previously :load Setup would look for a filename Setup.hs and load that, but that's wrong: we don't want :load Setup to always use the interpreter. So I made :load Setup treat Setup as a module name, which seems more correct. The problem is that now :load Setup will expect to find a module called Setup when it reads Setup.hs, which it often won't.

So I could probably add an exception for this case and make it work again, but it would be ugly, and hard to document without being thoroughly confusing. Can anyone think of a plan that is simple, easy to explain and implement, and doesn't break existing practice too much?

08/26/08 02:04:42 changed by igloo

Can Foo not search for Foo.o&hi, then Foo.hs, then Foo.lhs, and not require that the module name matches?

foo would do the same.

(follow-up: ↓ 9 ) 08/26/08 03:14:00 changed by simonmar

Yes, but that would be an exception. There are currently two cases:

  • a module name: search for the source file using the normal search semantics (-i search path, hierarchical module names etc.), load compiled code if available, require the module name in the file to be correct.
  • a filename ending in .hs or .lhs, or missing the extension: load exactly that file, which can contain any module, and in GHCi ignore any compiled version.

there would be an extra case, to come first:

  • for target X, if X.hs or X.lhs exists, load that file, which can contain any module, and in GHCi load compiled code if available.

this would change the behaviour of :load foo (it would load compiled code, whereas :load foo.hs wouldn't).

My main objection to this is that three cases feels like one too many to me.

08/26/08 03:19:58 changed by igloo

  • owner deleted.

08/26/08 04:37:02 changed by simonpj

I thought that we allowed the module name not to match the file name precisely (and only) when the module was called Main. That would collapse your first and third bullets which is what you wanted.

Also I suggest that plain M (no suffix) on the command line should fail altogether if you can't find M.hs or M.lhs, regardless of whether you are linking or not. And plain m (lower case) should fail too, since m can't be a module name. Stuff you want to link should have suffix .o or .a, shouldn't it?

Simon

(in reply to: ↑ 6 ) 08/26/08 04:42:23 changed by claus

(aside: would either runhaskell Main or adding module Setup where work?)

The first two cases sound right overall, but note that they already differ in strictness of checking:

  • via module name, the file name has to match
  • via file name, the module name doesn't need to match.

It would make more sense to have matching behaviour determined independently of the route, but the module-name route depends on strict matches to find the file (or ghc would have to check all sources for matching module names).

We could still have a flag ModuleFileNameMatch, but it wouldn't buy much.

The problem arises from Setup.[l]hs not having a module name, combined with the default being Main, which was meant to make finding and running Main.main in non-module code possible, while Cabal wants to find and run Setup.main in non-module code.

Could we simply change the default module name?

  • if the filename is a module name, File.[l]hs introduces module File (and module Main, if we still need that?)
  • if there is an explicit module name, it has to match the file name or be Main

08/27/08 01:30:40 changed by simonmar

  • owner set to simonmar.

08/27/08 01:39:45 changed by simonmar

Here is the latest plan. We came to the conclusion that mixing up the notion of whether a module is compiled to byte code or object code with whether it is specified as a filename or module name is too confusing. So we propose to restore the previous behaviour for specifying modules/filenames, and add a new way to say that a module is to be loaded as byte-code:

Prelude> :load *A
Compiling A                ( A.hs, interpreted )
*A>

The *-prefix forces the module to be loaded as byte-code. You can use any combination of * and non-* modules, and you can convert a non-* module to a * module later by saying :add *A.

The * syntax mirrors the same syntax used in the :module command and the prompt, so I think it's a consistent choice.

I'm validating the change now, please speak up if you dislike this idea or have a better one.

09/02/08 05:39:11 changed by simonmar

  • status changed from new to closed.
  • resolution set to fixed.
Wed Aug 27 03:24:14 PDT 2008  Simon Marlow <marlowsd@gmail.com>
  * re-fix of #1205, fix #2542

09/30/08 08:39:51 changed by simonmar

  • architecture changed from Unknown to Unknown/Multiple.

09/30/08 08:50:56 changed by simonmar

  • os changed from Unknown to Unknown/Multiple.