
On Tuesday, April 23, 2002, at 06:09 , Alastair Reid wrote:
[copied to original recipients along with the original bug report]
On ghc-bugs, Hal Daume reported problems with Hugs (and ghci) where importing IO.hs causes a module called Bar.IO (i.e., Bar/IO.hs) to be loaded - leading to the load to fail.
I've systematically tried every way of invoking Hugs (December 2001) that makes sense (and a few that don't) and didn't find any that worked. Here's what I tried:
cd /tmp mkdir Bar
cat > Bar/Foo.hs module Bar.Foo where import IO
cat > Bar/IO.hs module Bar.IO where
hugs Bar.Foo # unexpected failure: confuses Bar.IO for IO
hugs -P.: Bar.Foo # unexpected failure: confuses Bar.IO for IO
hugs Bar.Foo.hs # expected failure: Bar.Foo.hs doesn't exist
hugs Bar/Foo.hs # unexpected failure: confuses Bar.IO for IO
cd Bar hugs Bar.Foo # expected failure: Can't find Bar.Foo
hugs Foo # unexpected failure: confuses Bar.IO for IO
hugs -P..: Bar.Foo # unexpected failure: confuses Bar.IO for IO
Did I do the wrong thing or do we need to tweak the loader?
(I didn't test with import chasing turned off - could that be it?)
-- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
We're approaching a dark corner here, where the principle of a single, hierarchical module namespace clashes with the established idea of searching for modules along an externally defined directory path. In Hugs, and I think in ghci as well, the implementation of hierarchical modules allows a module hierarchy with several roots. Not only is it possible to define multiple roots in the search path, the current directory is also an implicit root, and if a module is being imported by another module, the directory where the importing module was found is another one. Now, since there's nothing that prevents the directory hierarchies starting at these roots from overlapping, we have a potential for ambiguity when we want to map module names to filenames. In the examples above, the module defined in Bar/IO.hs is given the name Bar.IO. However, according to the way we map module names onto files, Bar/IO.hs will also appear to be a valid implementation of module IO, since the directory Bar is implicitly an alternative root to the module hierarchy. One solution would then be to start parsing Bar/IO.hs until we can determine if its module name matches the name suggested by its file name and the current root. However, implementing such a check seems like a big hack, when the real problem is the questionable support for multiple roots. It's also not a trivial thing to do, since we would need to backtrack from parsing and continue the module search in case of a name mismatch. One might also argue that the problem is these extra roots that are implicitly added to the search path. Arguably, dropping the current directory and the directory of the importing module from the search path would solve the problems listed above. But there's still a possibility to list overlapping directories in the search path proper, so dropping the implicit directories wouldn't really cure the disease, only make it less prominent. Furthermore, this feature is there because it has been in Hugs for a long time, and many people seem to rely on it quite heavily. Still, the current status is unsatisfactory. Of the two ways forward pointed at above, dropping the implicit roots and putting the burden on the programmer to define consistent search paths is by far the easiest one to implement. However, one should bear in mind that this will disturb many people, particularly those who don't use hierarchical modules. Doing speculative parsing of module headers looks more robust, but it would indeed be a complicated way of resolving ambiguities that shouldn't be there in the first place. A fully satisfactory solution can't be obtained, I think, unless we make the whole module hierarchy single-rooted. That would make it harder to integrate local modules with the standard libraries, though, and would probably need some kind of module "mounting" facility to be practical. However, I don't believe we're ready for such an experiment just yet. All in all, dropping all implicit directories from the search path gets my vote. -- Johan