From f6aa7ddce829897f53dd72460248d297506f6ae8 Mon Sep 17 00:00:00 2001 From: simonmar Date: Tue, 26 Apr 2005 15:08:16 +0000 Subject: [PATCH] [project @ 2005-04-26 15:08:16 by simonmar] When chasing explicit imports, we now look for the module in both the home package and external packages, and complain if it is found in both: Chasing modules from: Overlap Cannot import `List': it was found in both overlap/List.hs and package haskell98-1.0. Possible fix: -ignore-package haskell98-1.0 (imported from overlap/Overlap.hs) Previously the home module would have been ignored in favour of the package module. It means we're doing a bit more searching, but the behaviour is less obscure. --- ghc/compiler/main/Finder.lhs | 134 +++++++++++++++++++++++++++--------------- 1 file changed, 85 insertions(+), 49 deletions(-) diff --git a/ghc/compiler/main/Finder.lhs b/ghc/compiler/main/Finder.lhs index 778f06d..14ec482 100644 --- a/ghc/compiler/main/Finder.lhs +++ b/ghc/compiler/main/Finder.lhs @@ -75,7 +75,7 @@ lookupFinderCache finder_cache mod_name = do return $! lookupModuleEnv fm mod_name -- ----------------------------------------------------------------------------- --- Locating modules +-- The two external entry points -- This is the main interface to the finder, which maps ModuleNames to -- Modules and ModLocations. @@ -90,6 +90,8 @@ lookupFinderCache finder_cache mod_name = do data FindResult = Found ModLocation PackageIdH -- the module was found + | FoundMultiple ModLocation PackageId + -- *error*: both a home module and a package module | PackageHidden PackageId -- for an explicit source import: the package containing the module is -- not exposed. @@ -99,76 +101,102 @@ data FindResult | NotFound [FilePath] -- the module was not found, the specified places were searched. +findModule :: HscEnv -> Module -> Bool -> IO FindResult +findModule = findModule' True + +findPackageModule :: HscEnv -> Module -> Bool -> IO FindResult +findPackageModule = findModule' False + + type LocalFindResult = MaybeErr [FilePath] FinderCacheEntry -- LocalFindResult is used for internal functions which -- return a more informative type; it's munged into -- the external FindResult by 'cached' -cached :: Bool - -> (DynFlags -> Module -> IO LocalFindResult) - -> HscEnv -> Module -> Bool -> IO FindResult -cached home_allowed wrapped_fn hsc_env name explicit - = do { -- First try the cache - let cache = hsc_FC hsc_env - ; mb_entry <- lookupFinderCache cache name - ; case mb_entry of { - Just old_entry -> return (found old_entry) ; - Nothing -> do - - { -- Now try the wrapped function - mb_entry <- wrapped_fn (hsc_dflags hsc_env) name - ; case mb_entry of - Failed paths -> return (NotFound paths) - Succeeded new_entry -> do { addToFinderCache cache name new_entry - ; return (found new_entry) } - }}} - where +findModule' :: Bool -> HscEnv -> Module -> Bool -> IO FindResult +findModule' home_allowed hsc_env name explicit + = do -- First try the cache + mb_entry <- lookupFinderCache cache name + case mb_entry of + Just old_entry -> return $! found old_entry + Nothing -> not_cached + + where + cache = hsc_FC hsc_env + dflags = hsc_dflags hsc_env + -- We've found the module, so the remaining question is -- whether it's visible or not - found :: FinderCacheEntry -> FindResult - found (loc, Nothing) + found :: FinderCacheEntry -> FindResult + found (loc, Nothing) | home_allowed = Found loc HomePackage | otherwise = NotFound [] - found (loc, Just (pkg, exposed_mod)) + found (loc, Just (pkg, exposed_mod)) | explicit && not exposed_mod = ModuleHidden pkg_name | explicit && not (exposed pkg) = PackageHidden pkg_name - | otherwise = Found loc (ExtPackage (mkPackageId (package pkg))) + | otherwise = + Found loc (ExtPackage (mkPackageId (package pkg))) where pkg_name = packageConfigId pkg + found_new entry = do + addToFinderCache cache name entry + return $! found entry + + not_cached + | not home_allowed = do + j <- findPackageModule' dflags name + case j of + Failed paths -> return (NotFound paths) + Succeeded entry -> found_new entry + + | home_allowed && explicit = do + -- for an explict home import, we try looking for + -- both a package module and a home module, and report + -- a FoundMultiple if we find both. + j <- findHomeModule' dflags name + case j of + Failed home_files -> do + r <- findPackageModule' dflags name + case r of + Failed pkg_files -> + return (NotFound (home_files ++ pkg_files)) + Succeeded entry -> + found_new entry + Succeeded entry@(loc,_) -> do + r <- findPackageModule' dflags name + case r of + Failed pkg_files -> found_new entry + Succeeded (_,Just (pkg,_)) -> + return (FoundMultiple loc (packageConfigId pkg)) + Succeeded _ -> + panic "findModule: shouldn't happen" + + -- implicit home imports: check for package modules first, + -- because that's the quickest (doesn't involve filesystem + -- operations). + | home_allowed && not explicit = do + r <- findPackageModule' dflags name + case r of + Failed pkg_files -> do + j <- findHomeModule' dflags name + case j of + Failed home_files -> + return (NotFound (home_files ++ pkg_files)) + Succeeded entry -> + found_new entry + Succeeded entry -> + found_new entry + + addHomeModuleToFinder :: HscEnv -> Module -> ModLocation -> IO () addHomeModuleToFinder hsc_env mod loc = addToFinderCache (hsc_FC hsc_env) mod (loc, Nothing) -- ----------------------------------------------------------------------------- --- The two external entry points - - -findModule :: HscEnv -> Module -> Bool -> IO FindResult -findModule = cached True findModule' - -findPackageModule :: HscEnv -> Module -> Bool -> IO FindResult -findPackageModule = cached False findPackageModule' - --- ----------------------------------------------------------------------------- -- The internal workers -findModule' :: DynFlags -> Module -> IO LocalFindResult --- Find home or package module -findModule' dflags name = do - r <- findPackageModule' dflags name - case r of - Failed pkg_files -> do - j <- findHomeModule' dflags name - case j of - Failed home_files -> - return (Failed (home_files ++ pkg_files)) - other_result - -> return other_result - other_result - -> return other_result - findHomeModule' :: DynFlags -> Module -> IO LocalFindResult findHomeModule' dflags mod = do let home_path = importPaths dflags @@ -422,6 +450,14 @@ dots_to_slashes = map (\c -> if c == '.' then '/' else c) -- Error messages cantFindError :: DynFlags -> Module -> FindResult -> SDoc +cantFindError dflags mod_name (FoundMultiple loc pkg) + = hang (ptext SLIT("Cannot import") <+> quotes (ppr mod_name) <> colon) 2 ( + sep [ptext SLIT("it was found in both") <+> + (case ml_hs_file loc of Nothing -> ptext SLIT("") + Just f -> text f), + ptext SLIT("and package") <+> ppr pkg <> char '.'] $$ + ptext SLIT("Possible fix: -ignore-package") <+> ppr pkg + ) cantFindError dflags mod_name find_result = hang (ptext SLIT("Could not find module") <+> quotes (ppr mod_name) <> colon) 2 more_info -- 1.7.10.4