Opened 4 years ago

Closed 3 years ago

#9764 closed feature request (wontfix)

Home package modules silently override available modules from package database

Reported by: ezyang Owned by: ezyang
Priority: normal Milestone:
Component: Compiler Version: 7.9
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC accepts invalid program Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by ezyang)

To see this, define a module with the same name as some module in base. GHC will compile this:

module Data.List where
  foo = 2

module A where
  import Data.List
  x = print foo

This behavior is intentional; the most compelling reason of behaving this way is that if you are calling ghc without -hide-all-packages, some random package you installed which just happened to provide a module name that conflicted with yours could cause your code to stop compiling if we treated the package database and home packages equally.

However, this behavior seems undesirable when -hide-all-packages is provided; at the very least, it seems like you might want to provide a warning that you're defining a module which conflicts with a module from a package you have exposed.

This behavior will be further undesirable when signatures come into the picture. Now, I will want to include a package containing a signature for A, and FURTHERMORE I may want to declare a signature A.hsig in the local package which augments this signature with some extra declarations I need. Under the current behavior, the externally imported signature is just ignored entirely, even though I wanted them to be merged together. (A counter argument is that this is confusing for users, who will see the use of a declaration, browse to the local hsig file, and not see it defined; thus this mode of use should be disallowed.)

My proposal is to switch the behavior so that we don't prefer home modules if -hide-all-packages is provided. What's not great about this proposal is that it adds yet another discrepancy between bare GHC use and GHC use with -hide-all-packages. I'm interested to know what people would like.

Change History (6)

comment:1 Changed 4 years ago by ezyang

Description: modified (diff)

comment:2 Changed 4 years ago by simonpj

Wait. If you say -hide-all-packages then there are no packages in scope, so how can there be any conflict?

Perhaps you mean to propose this:

  • If you have an explicit -package p flag
  • And a home-package module whose name conflicts with one exposed by p
  • Then at least warn of the conflict

Was that what you meant? That would not imply any discrepancies, would it?


comment:3 Changed 4 years ago by ezyang

That is not what I was proposing, but it sounds much better! And I agree, in that case, there would be no discrepancies.

comment:4 Changed 4 years ago by Yuras

If I understand it correctly, it will break my -Wall'd code. I sometimes have local Prelude module to work around some incompatibilities between versions:

{-# LANGUAGE PackageImports #-}
module Prelude
module P
#if MIN_VERSION_base(4,6,0)
import "base" Prelude as P
import "base" Prelude as P hiding (catch)

There are other ways to do that, so I'm not advocating against the proposal. But that is a legitimate use case IMO, and it can be used not only for Prelude. So at least a switch to turn off the warning should be provided, please.

comment:5 Changed 4 years ago by ezyang

In GHC 7.10, there will be TWO ways to do the specific use-case you're asking for!

The first is the new -prelude-is flag #9499, which will let you set Prelude to be a module not named Prelude.

The second is package renaming #9375, which means you can include base but rename Prelude to another name BasePrelude.

comment:6 Changed 3 years ago by ezyang

Resolution: wontfix
Status: newclosed

Our resolution for 7.10 and the indefinite future is this:

  1. Normal modules do NOT warn about shadowing, so we don't break Wall'd code.
  2. Signature modules silently get merged with the available modules in the context.

So we just treat normal modules differently from signature modules. This is a little different from how the Backpack paper works, but I don't think there is any difference in expressivity.

Note: See TracTickets for help on using tickets.