X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Frename%2FRnHiFiles.lhs;h=dd4baca37ba969e728ae96ed0a1931dcf6baf64e;hb=80d58cf35153143860111297760e76e0b3244df8;hp=42240c10f8d71947b07ae781875724e46817f8fb;hpb=83eef621e4a4fbb6c1343304ec638cafd6c9dc09;p=ghc-hetmet.git diff --git a/ghc/compiler/rename/RnHiFiles.lhs b/ghc/compiler/rename/RnHiFiles.lhs index 42240c1..dd4baca 100644 --- a/ghc/compiler/rename/RnHiFiles.lhs +++ b/ghc/compiler/rename/RnHiFiles.lhs @@ -11,56 +11,55 @@ module RnHiFiles ( lookupFixityRn, - getTyClDeclBinders, - removeContext -- removeContext probably belongs somewhere else + getTyClDeclBinders ) where #include "HsVersions.h" +import DriverState ( GhcMode(..), v_GhcMode ) +import DriverUtil ( splitFilename ) import CmdLineOpts ( opt_IgnoreIfacePragmas ) import HscTypes ( ModuleLocation(..), ModIface(..), emptyModIface, - VersionInfo(..), + VersionInfo(..), ImportedModuleInfo, lookupIfaceByModName, ImportVersion, WhetherHasOrphans, IsBootInterface, DeclsMap, GatedDecl, IfaceInsts, IfaceRules, AvailInfo, GenAvailInfo(..), Avails, Deprecations(..) ) import HsSyn ( TyClDecl(..), InstDecl(..), - HsType(..), FixitySig(..), RuleDecl(..), - tyClDeclNames, tyClDeclSysNames - ) -import RdrHsSyn ( RdrNameTyClDecl, RdrNameInstDecl, RdrNameRuleDecl, - extractHsTyRdrNames + HsType(..), HsPred(..), FixitySig(..), RuleDecl(..), + tyClDeclNames, tyClDeclSysNames, hsTyVarNames ) +import RdrHsSyn ( RdrNameTyClDecl, RdrNameInstDecl, RdrNameRuleDecl ) +import RnHsSyn ( extractHsTyNames_s ) import BasicTypes ( Version, defaultFixity ) +import RnTypes ( rnHsType ) import RnEnv import RnMonad -import ParseIface ( parseIface, IfaceStuff(..) ) +import ParseIface ( parseIface ) -import Name ( Name {-instance NamedThing-}, nameOccName, - nameModule, isLocalName, nameIsLocalOrFrom, - NamedThing(..), +import Name ( Name {-instance NamedThing-}, + nameModule, isLocalName, nameIsLocalOrFrom ) -import Name ( mkNameEnv, extendNameEnv ) -import Module ( Module, - moduleName, isHomeModule, - ModuleName, WhereFrom(..), - extendModuleEnv, mkVanillaModule - ) -import RdrName ( RdrName, rdrNameOcc ) +import NameEnv +import NameSet +import Module +import RdrName ( rdrNameOcc ) import SrcLoc ( mkSrcLoc ) import Maybes ( maybeToBool, orElse ) import StringBuffer ( hGetStringBuffer ) import FastString ( mkFastString ) import ErrUtils ( Message ) -import Finder ( findModule ) +import Finder ( findModule, findPackageModule ) import Lex import FiniteMap +import ListSetOps ( minusList ) import Outputable import Bag import Config +import IOExts import Directory \end{code} @@ -93,7 +92,10 @@ loadInterface doc mod from = tryLoadInterface doc mod from `thenRn` \ (ifaces, maybe_err) -> case maybe_err of Nothing -> returnRn ifaces - Just err -> failWithRn ifaces err + Just err -> failWithRn ifaces (elaborate err) + where + elaborate err = hang (ptext SLIT("failed to load interface for") <+> quotes (ppr mod) <> colon) + 4 err tryLoadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d (ModIface, Maybe Message) -- Returns (Just err) if an error happened @@ -106,6 +108,7 @@ tryLoadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d (ModIface, Maybe Me -- (If the load fails, we plug in a vanilla placeholder) tryLoadInterface doc_str mod_name from = getHomeIfaceTableRn `thenRn` \ hit -> + getModuleRn `thenRn` \ this_mod -> getIfacesRn `thenRn` \ ifaces@(Ifaces { iPIT = pit }) -> -- CHECK WHETHER WE HAVE IT ALREADY @@ -148,8 +151,16 @@ tryLoadInterface doc_str mod_name from warnCheckRn (not redundant_source_import) (warnRedundantSourceImport mod_name) `thenRn_` + -- Check that we aren't importing ourselves. + -- That only happens in Rename.checkOldIface, + -- which doesn't call tryLoadInterface + warnCheckRn + (not (isHomeModule this_mod) || moduleName this_mod /= mod_name) + (warnSelfImport this_mod) `thenRn_` + -- READ THE MODULE IN - findAndReadIface doc_str mod_name hi_boot_file `thenRn` \ read_result -> + findAndReadIface doc_str mod_name hi_boot_file + `thenRn` \ read_result -> case read_result of { Left err -> -- Not found, so add an empty export env to the Ifaces map -- so that we don't look again @@ -198,7 +209,14 @@ tryLoadInterface doc_str mod_name from ImportByUser -> addModDeps mod is_loaded (pi_usages iface) mod_map other -> mod_map mod_map2 = delFromFM mod_map1 mod_name - is_loaded m = maybeToBool (lookupIfaceByModName hit pit m) + + this_mod_name = moduleName this_mod + is_loaded m = m == this_mod_name + || maybeToBool (lookupIfaceByModName hit pit m) + -- We treat the currently-being-compiled module as 'loaded' because + -- even though it isn't yet in the HIT or PIT; otherwise it gets + -- put into iImpModInfo, and then spat out into its own interface + -- file as a dependency -- Now add info about this module to the PIT has_orphans = pi_orphan iface @@ -228,7 +246,7 @@ tryLoadInterface doc_str mod_name from ----------------------------------------------------- addModDeps :: Module - -> (ModuleName -> Bool) -- True for module interfaces + -> (ModuleName -> Bool) -- True for modules that are already loaded -> [ImportVersion a] -> ImportedModuleInfo -> ImportedModuleInfo -- (addModDeps M ivs deps) @@ -241,8 +259,7 @@ addModDeps mod is_loaded new_deps mod_deps -- and in that case, forget about the boot indicator filtered_new_deps :: [(ModuleName, (WhetherHasOrphans, IsBootInterface))] filtered_new_deps - | isHomeModule mod - = [ (imp_mod, (has_orphans, is_boot)) + | isHomeModule mod = [ (imp_mod, (has_orphans, is_boot)) | (imp_mod, has_orphans, is_boot, _) <- new_deps, not (is_loaded imp_mod) ] @@ -262,13 +279,12 @@ addModDeps mod is_loaded new_deps mod_deps loadExports :: (Version, [ExportItem]) -> RnM d (Version, [(ModuleName,Avails)]) loadExports (vers, items) - = getModuleRn `thenRn` \ this_mod -> - mapRn (loadExport this_mod) items `thenRn` \ avails_s -> + = mapRn loadExport items `thenRn` \ avails_s -> returnRn (vers, avails_s) -loadExport :: Module -> ExportItem -> RnM d (ModuleName, Avails) -loadExport this_mod (mod, entities) +loadExport :: ExportItem -> RnM d (ModuleName, Avails) +loadExport (mod, entities) = mapRn (load_entity mod) entities `thenRn` \ avails -> returnRn (mod, avails) where @@ -347,23 +363,52 @@ loadInstDecl mod insts decl@(InstDecl inst_ty _ _ _ _) -- instance Foo a => Baz (T a) where ... -- -- Here the gates are Baz and T, but *not* Foo. + -- + -- HOWEVER: functional dependencies make things more complicated + -- class C a b | a->b where ... + -- instance C Foo Baz where ... + -- Here, the gates are really only C and Foo, *not* Baz. + -- That is, if C and Foo are visible, even if Baz isn't, we must + -- slurp the decl. + -- + -- Rather than take fundeps into account "properly", we just slurp + -- if C is visible and *any one* of the Names in the types + -- This is a slightly brutal approximation, but most instance decls + -- are regular H98 ones and it's perfect for them. + -- + -- NOTICE that we rename the type before extracting its free + -- variables. The free-variable finder for a renamed HsType + -- does the Right Thing for built-in syntax like [] and (,). + initIfaceRnMS mod ( + rnHsType (text "In an interface instance decl") inst_ty + ) `thenRn` \ inst_ty' -> let - munged_inst_ty = removeContext inst_ty - free_names = extractHsTyRdrNames munged_inst_ty + (tvs,(cls,tys)) = get_head inst_ty' + free_tcs = nameSetToList (extractHsTyNames_s tys) `minusList` hsTyVarNames tvs + + gate_fn vis_fn = vis_fn cls && (null free_tcs || any vis_fn free_tcs) + -- Here is the implementation of HOWEVER above + -- (Note that we do let the inst decl in if it mentions + -- no tycons at all. Hence the null free_ty_names.) in - mapRn lookupIfaceName free_names `thenRn` \ gate_names -> - returnRn ((gate_names, (mod, decl)) `consBag` insts) + returnRn ((gate_fn, (mod, decl)) `consBag` insts) -- In interface files, the instance decls now look like -- forall a. Foo a -> Baz (T a) --- so we have to strip off function argument types as well --- as the bit before the '=>' (which is always empty in interface files) -removeContext (HsForAllTy tvs cxt ty) = HsForAllTy tvs [] (removeFuns ty) -removeContext ty = removeFuns ty +-- so we have to strip off function argument types, +-- as well as the bit before the '=>' (which is always +-- empty in interface files) +-- +-- The parser ensures the type will have the right shape. +-- (e.g. see ParseUtil.checkInstType) + +get_head (HsForAllTy (Just tvs) _ tau) = (tvs, get_head1 tau) +get_head tau = ([], get_head1 tau) + +get_head1 (HsFunTy _ ty) = get_head1 ty +get_head1 (HsPredTy (HsClassP cls tys)) = (cls,tys) -removeFuns (HsFunTy _ ty) = removeFuns ty -removeFuns ty = ty ----------------------------------------------------- @@ -384,9 +429,9 @@ loadRules mod (rule_bag, n_slurped) (version, rules) loadRule :: Module -> RdrNameRuleDecl -> RnM d (GatedDecl RdrNameRuleDecl) -- "Gate" the rule simply by whether the rule variable is -- needed. We can refine this later. -loadRule mod decl@(IfaceRule _ _ var _ _ src_loc) +loadRule mod decl@(IfaceRule _ _ _ var _ _ src_loc) = lookupIfaceName var `thenRn` \ var_name -> - returnRn ([var_name], (mod, decl)) + returnRn (\vis_fn -> vis_fn var_name, (mod, decl)) ----------------------------------------------------- @@ -419,6 +464,9 @@ It's used for both source code (from @availsFromDecl@) and interface files It doesn't deal with source-code specific things: @ValD@, @DefD@. They are handled by the sourc-code specific stuff in @RnNames@. + *** See "THE NAMING STORY" in HsDecls **** + + \begin{code} getTyClDeclBinders :: Module @@ -458,7 +506,20 @@ findAndReadIface :: SDoc -> ModuleName findAndReadIface doc_str mod_name hi_boot_file = traceRn trace_msg `thenRn_` - ioToRnM (findModule mod_name) `thenRn` \ maybe_found -> + -- In interactive or --make mode, we are *not allowed* to demand-load + -- a home package .hi file. So don't even look for them. + -- This helps in the case where you are sitting in eg. ghc/lib/std + -- and start up GHCi - it won't complain that all the modules it tries + -- to load are found in the home location. + ioToRnM_no_fail (readIORef v_GhcMode) `thenRn` \ mode -> + let home_allowed = hi_boot_file || + mode `notElem` [ DoInteractive, DoMake ] + in + + ioToRnM (if home_allowed + then findModule mod_name + else findPackageModule mod_name) `thenRn` \ maybe_found -> + case maybe_found of Right (Just (wanted_mod,locn)) @@ -468,9 +529,16 @@ findAndReadIface doc_str mod_name hi_boot_file Left bad -> returnRn (Left bad) Right iface -> let read_mod = pi_mod iface - in warnCheckRn (wanted_mod == read_mod) - (hiModuleNameMismatchWarn wanted_mod - read_mod) `thenRn_` + in -- check that the module names agree + checkRn + (wanted_mod == read_mod) + (hiModuleNameMismatchWarn wanted_mod read_mod) + `thenRn_` + -- check that the package names agree + warnCheckRn + (modulePackage wanted_mod == modulePackage read_mod) + (packageNameMismatchWarn wanted_mod read_mod) + `thenRn_` returnRn (Right (wanted_mod, iface)) -- Can't find it other -> traceRn (ptext SLIT("...not found")) `thenRn_` @@ -489,9 +557,10 @@ mkHiPath hi_boot_file locn if b then returnRn hi_boot_ver_path else returnRn hi_boot_path | otherwise = returnRn hi_path - where (Just hi_path) = ml_hi_file locn - hi_boot_path = hi_path ++ "-boot" - hi_boot_ver_path = hi_path ++ "-boot-" ++ cHscIfaceFileVersion + where hi_path = ml_hi_file locn + (hi_base, _hi_suf) = splitFilename hi_path + hi_boot_path = hi_base ++ ".hi-boot" + hi_boot_ver_path = hi_base ++ ".hi-boot-" ++ cHscIfaceFileVersion \end{code} @readIface@ tries just the one file. @@ -501,7 +570,8 @@ readIface :: String -> RnM d (Either Message ParsedIface) -- Nothing <=> file not found, or unreadable, or illegible -- Just x <=> successfully found and parsed readIface file_path - = traceRn (ptext SLIT("readIFace") <+> text file_path) `thenRn_` + = --ioToRnM (putStrLn ("reading iface " ++ file_path)) `thenRn_` + traceRn (ptext SLIT("readIFace") <+> text file_path) `thenRn_` ioToRnM (hGetStringBuffer False file_path) `thenRn` \ read_result -> case read_result of { @@ -509,13 +579,8 @@ readIface file_path Right contents -> case parseIface contents init_parser_state of - POk _ (PIface iface) -> returnRn (Right iface) + POk _ iface -> returnRn (Right iface) PFailed err -> bale_out err - parse_result -> bale_out empty - -- This last case can happen if the interface file is (say) empty - -- in which case the parser thinks it looks like an IdInfo or - -- something like that. Just an artefact of the fact that the - -- parser is used for several purposes at once. } where init_parser_state = PState{ bol = 0#, atbol = 1#, @@ -526,15 +591,14 @@ readIface file_path bale_out err = returnRn (Left (badIfaceFile file_path err)) \end{code} - %********************************************************* %* * \subsection{Looking up fixities} %* * %********************************************************* -@lookupFixityRn@ has to be in RnIfaces (or RnHiFiles) because -it calls @loadHomeInterface@. +@lookupFixityRn@ has to be in RnIfaces (or RnHiFiles), instead of +its obvious home in RnEnv, because it calls @loadHomeInterface@. lookupFixity is a bit strange. @@ -559,13 +623,15 @@ lookupFixityRn name returnRn (lookupLocalFixity local_fix_env name) else -- It's imported - -- For imported names, we have to get their fixities by doing a loadHomeInterface, - -- and consulting the Ifaces that comes back from that, because the interface - -- file for the Name might not have been loaded yet. Why not? Suppose you import module A, - -- which exports a function 'f', which is defined in module B. Then B isn't loaded - -- right away (after all, it's possible that nothing from B will be used). - -- When we come across a use of 'f', we need to know its fixity, and it's then, - -- and only then, that we load B.hi. That is what's happening here. + -- For imported names, we have to get their fixities by doing a + -- loadHomeInterface, and consulting the Ifaces that comes back + -- from that, because the interface file for the Name might not + -- have been loaded yet. Why not? Suppose you import module A, + -- which exports a function 'f', which is defined in module B. + -- Then B isn't loaded right away (after all, it's possible that + -- nothing from B will be used). When we come across a use of + -- 'f', we need to know its fixity, and it's then, and only + -- then, that we load B.hi. That is what's happening here. loadHomeInterface doc name `thenRn` \ iface -> returnRn (lookupNameEnv (mi_fixities iface) name `orElse` defaultFixity) where @@ -598,8 +664,19 @@ hiModuleNameMismatchWarn requested_mod read_mod = , ppr read_mod ] +packageNameMismatchWarn :: Module -> Module -> Message +packageNameMismatchWarn requested_mod read_mod = + fsep [ ptext SLIT("Module"), quotes (ppr requested_mod), + ptext SLIT("is located in package"), + quotes (ptext (modulePackage requested_mod)), + ptext SLIT("but its interface file claims it is part of package"), + quotes (ptext (modulePackage read_mod)) + ] + warnRedundantSourceImport mod_name = ptext SLIT("Unnecessary {- SOURCE -} in the import of module") <+> quotes (ppr mod_name) -\end{code} +warnSelfImport mod + = ptext SLIT("Importing my own interface: module") <+> ppr mod +\end{code}