summaryrefslogtreecommitdiff
path: root/compiler/iface/LoadIface.hs
diff options
context:
space:
mode:
authorEdward Z. Yang <ezyang@cs.stanford.edu>2015-07-20 20:16:35 -0700
committerEdward Z. Yang <ezyang@cs.stanford.edu>2015-07-20 20:16:35 -0700
commit0c6c015d42c2bd0ee008f790c7c0cb4c5b78ca6b (patch)
treece6b716a99806eb3b3e60a8e1aaecce8799e7593 /compiler/iface/LoadIface.hs
parentb4ef8b8badaa43872a843778e8fa9da943955d38 (diff)
downloadhaskell-0c6c015d42c2bd0ee008f790c7c0cb4c5b78ca6b.tar.gz
Revert "Revert "Change loadSrcInterface to return a list of ModIface""
This reverts commit c60704fc405149407c155e297433f1cc299ae58a.
Diffstat (limited to 'compiler/iface/LoadIface.hs')
-rw-r--r--compiler/iface/LoadIface.hs50
1 files changed, 44 insertions, 6 deletions
diff --git a/compiler/iface/LoadIface.hs b/compiler/iface/LoadIface.hs
index 2a8943ca11..bdfba7c9bd 100644
--- a/compiler/iface/LoadIface.hs
+++ b/compiler/iface/LoadIface.hs
@@ -234,26 +234,61 @@ needWiredInHomeIface _ = False
************************************************************************
-}
+-- Note [Un-ambiguous multiple interfaces]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- When a user writes an import statement, this usually causes a *single*
+-- interface file to be loaded. However, the game is different when
+-- signatures are being imported. Suppose in packages p and q we have
+-- signatures:
+--
+-- module A where
+-- foo :: Int
+--
+-- module A where
+-- bar :: Int
+--
+-- If both packages are exposed and I am importing A, I should see a
+-- "unified" signature:
+--
+-- module A where
+-- foo :: Int
+-- bar :: Int
+--
+-- The way we achieve this is having the module lookup for A load and return
+-- multiple interface files, which we will then process as if there were
+-- "multiple" imports:
+--
+-- import "p" A
+-- import "q" A
+--
+-- Doing so does not cause any ambiguity, because any overlapping identifiers
+-- are guaranteed to have the same name if the backing implementations of the
+-- two signatures are the same (a condition which is checked by 'Packages'.)
+
+
-- | Load the interface corresponding to an @import@ directive in
-- source code. On a failure, fail in the monad with an error message.
+-- See Note [Un-ambiguous multiple interfaces] for why the return type
+-- is @[ModIface]@
loadSrcInterface :: SDoc
-> ModuleName
-> IsBootInterface -- {-# SOURCE #-} ?
-> Maybe FastString -- "package", if any
- -> RnM ModIface
+ -> RnM [ModIface]
loadSrcInterface doc mod want_boot maybe_pkg
= do { res <- loadSrcInterface_maybe doc mod want_boot maybe_pkg
; case res of
- Failed err -> failWithTc err
- Succeeded iface -> return iface }
+ Failed err -> failWithTc err
+ Succeeded ifaces -> return ifaces }
--- | Like 'loadSrcInterface', but returns a 'MaybeErr'.
+-- | Like 'loadSrcInterface', but returns a 'MaybeErr'. See also
+-- Note [Un-ambiguous multiple interfaces]
loadSrcInterface_maybe :: SDoc
-> ModuleName
-> IsBootInterface -- {-# SOURCE #-} ?
-> Maybe FastString -- "package", if any
- -> RnM (MaybeErr MsgDoc ModIface)
+ -> RnM (MaybeErr MsgDoc [ModIface])
loadSrcInterface_maybe doc mod want_boot maybe_pkg
-- We must first find which Module this import refers to. This involves
@@ -262,9 +297,12 @@ loadSrcInterface_maybe doc mod want_boot maybe_pkg
-- interface; it will call the Finder again, but the ModLocation will be
-- cached from the first search.
= do { hsc_env <- getTopEnv
+ -- ToDo: findImportedModule should return a list of interfaces
; res <- liftIO $ findImportedModule hsc_env mod maybe_pkg
; case res of
- Found _ mod -> initIfaceTcRn $ loadInterface doc mod (ImportByUser want_boot)
+ Found _ mod -> fmap (fmap (:[]))
+ . initIfaceTcRn
+ $ loadInterface doc mod (ImportByUser want_boot)
err -> return (Failed (cannotFindInterface (hsc_dflags hsc_env) mod err)) }
-- | Load interface directly for a fully qualified 'Module'. (This is a fairly