X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Frename%2FRnNames.lhs;h=6c35ef11a22aa39c633c53bc8ebd7659b18d77f7;hp=7ae180cde4e3a8e77ee51367aa41684efd28b623;hb=ec0b859902e717c24addff49f9a83efb927fb669;hpb=49732aefa0fac9e8c844c249070030df74c03c9b diff --git a/compiler/rename/RnNames.lhs b/compiler/rename/RnNames.lhs index 7ae180c..6c35ef1 100644 --- a/compiler/rename/RnNames.lhs +++ b/compiler/rename/RnNames.lhs @@ -8,7 +8,7 @@ module RnNames ( rnImports, importsFromLocalDecls, rnExports, getLocalDeclBinders, extendRdrEnvRn, - reportUnusedNames, reportDeprecations + reportUnusedNames, finishDeprecations ) where #include "HsVersions.h" @@ -17,12 +17,12 @@ import DynFlags ( DynFlag(..), GhcMode(..), DynFlags(..) ) import HsSyn ( IE(..), ieName, ImportDecl(..), LImportDecl, ForeignDecl(..), HsGroup(..), HsValBinds(..), Sig(..), collectHsBindLocatedBinders, tyClDeclNames, - instDeclATs, isIdxTyDecl, + instDeclATs, isFamInstDecl, LIE ) import RnEnv import RnHsDoc ( rnHsDoc ) import IfaceEnv ( ifaceExportNames ) -import LoadIface ( loadSrcInterface ) +import LoadIface ( loadSrcInterface, loadSysInterface ) import TcRnMonad hiding (LIE) import PrelNames @@ -30,28 +30,12 @@ import Module import Name import NameEnv import NameSet -import OccName ( srcDataName, pprNonVarNameSpace, - occNameSpace, - OccEnv, mkOccEnv, mkOccEnv_C, lookupOccEnv, - emptyOccEnv, extendOccEnv ) -import HscTypes ( GenAvailInfo(..), AvailInfo, availNames, availName, - HomePackageTable, PackageIfaceTable, - mkPrintUnqualified, availsToNameSet, - Deprecs(..), ModIface(..), Dependencies(..), - lookupIfaceByModule, ExternalPackageState(..) - ) -import RdrName ( RdrName, rdrNameOcc, setRdrNameSpace, Parent(..), - GlobalRdrEnv, mkGlobalRdrEnv, GlobalRdrElt(..), - emptyGlobalRdrEnv, plusGlobalRdrEnv, globalRdrEnvElts, - extendGlobalRdrEnv, lookupGlobalRdrEnv, - lookupGRE_RdrName, lookupGRE_Name, - Provenance(..), ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..), - importSpecLoc, importSpecModule, isLocalGRE, pprNameProvenance, - unQualSpecOK, qualSpecOK ) +import OccName +import HscTypes +import RdrName import Outputable import Maybes -import SrcLoc ( Located(..), mkGeneralSrcSpan, getLoc, - unLoc, noLoc, srcLocSpan, SrcSpan ) +import SrcLoc import FiniteMap import ErrUtils import BasicTypes ( DeprecTxt ) @@ -159,7 +143,7 @@ rnImportDecl this_mod (L loc (ImportDecl loc_imp_mod_name want_boot let imp_mod = mi_module iface deprecs = mi_deprecs iface - is_orph = mi_orphan iface + orph_iface = mi_orphan iface has_finsts = mi_finsts iface deps = mi_deps iface @@ -202,9 +186,9 @@ rnImportDecl this_mod (L loc (ImportDecl loc_imp_mod_name want_boot let -- Compute new transitive dependencies - orphans | is_orph = ASSERT( not (imp_mod `elem` dep_orphs deps) ) - imp_mod : dep_orphs deps - | otherwise = dep_orphs deps + orphans | orph_iface = ASSERT( not (imp_mod `elem` dep_orphs deps) ) + imp_mod : dep_orphs deps + | otherwise = dep_orphs deps finsts | has_finsts = ASSERT( not (imp_mod `elem` dep_finsts deps) ) imp_mod : dep_finsts deps @@ -352,7 +336,7 @@ getLocalDeclBinders gbl_env (HsGroup {hs_valds = ValBindsIn val_decls val_sigs, for_hs_bndrs = [nm | L _ (ForeignImport nm _ _) <- foreign_decls] new_tc tc_decl - | isIdxTyDecl (unLoc tc_decl) + | isFamInstDecl (unLoc tc_decl) = do { main_name <- lookupFamInstDeclBndr mod main_rdr ; sub_names <- mappM (newTopSrcBinder mod) sub_rdrs ; return (AvailTC main_name sub_names) } @@ -704,41 +688,44 @@ type ExportOccMap = OccEnv (Name, IE RdrName) -- it came from. It's illegal to export two distinct things -- that have the same occurrence name -rnExports :: Bool -- False => no 'module M(..) where' header at all +rnExports :: Bool -- False => no 'module M(..) where' header at all -> Maybe [LIE RdrName] -- Nothing => no explicit export list - -> RnM (Maybe [LIE Name], [AvailInfo]) + -> TcGblEnv + -> RnM TcGblEnv -- Complains if two distinct exports have same OccName -- Warns about identical exports. -- Complains about exports items not in scope -rnExports explicit_mod exports - = do TcGblEnv { tcg_mod = this_mod, - tcg_rdr_env = rdr_env, - tcg_imports = imports } <- getGblEnv - +rnExports explicit_mod exports + tcg_env@(TcGblEnv { tcg_mod = this_mod, + tcg_rdr_env = rdr_env, + tcg_imports = imports }) + = do { -- If the module header is omitted altogether, then behave -- as if the user had written "module Main(main) where..." -- EXCEPT in interactive mode, when we behave as if he had -- written "module Main where ..." -- Reason: don't want to complain about 'main' not in scope -- in interactive mode - ghc_mode <- getGhcMode - real_exports <- - case () of - () | explicit_mod - -> return exports - | ghc_mode == Interactive - -> return Nothing - | otherwise - -> do mainName <- lookupGlobalOccRn main_RDR_Unqual - return (Just ([noLoc (IEVar main_RDR_Unqual)])) - -- ToDo: the 'noLoc' here is unhelpful if 'main' turns - -- out to be out of scope - - (exp_spec, avails) <- exports_from_avail real_exports rdr_env imports this_mod - - return (exp_spec, nubAvails avails) -- Combine families + ; ghc_mode <- getGhcMode + ; let real_exports + | explicit_mod = exports + | ghc_mode == Interactive = Nothing + | otherwise = Just ([noLoc (IEVar main_RDR_Unqual)]) + -- ToDo: the 'noLoc' here is unhelpful if 'main' + -- turns out to be out of scope + + ; (rn_exports, avails) <- exports_from_avail real_exports rdr_env imports this_mod + ; let final_avails = nubAvails avails -- Combine families + + ; return (tcg_env { tcg_exports = final_avails, + tcg_rn_exports = case tcg_rn_exports tcg_env of + Nothing -> Nothing + Just _ -> rn_exports, + tcg_dus = tcg_dus tcg_env `plusDU` + usesOnly (availsToNameSet final_avails) }) } + exports_from_avail :: Maybe [LIE RdrName] -- Nothing => no explicit export list @@ -815,14 +802,13 @@ exports_from_avail (Just rdr_items) rdr_env imports this_mod return (IEVar (gre_name gre), greAvail gre) lookup_ie (IEThingAbs rdr) - = do name <- lookupGlobalOccRn rdr - case lookupGRE_RdrName rdr rdr_env of - [] -> panic "RnNames.lookup_ie" - elt:_ -> case gre_par elt of - NoParent -> return (IEThingAbs name, - AvailTC name [name]) - ParentIs p -> return (IEThingAbs name, - AvailTC p [name]) + = do gre <- lookupGreRn rdr + let name = gre_name gre + case gre_par gre of + NoParent -> return (IEThingAbs name, + AvailTC name [name]) + ParentIs p -> return (IEThingAbs name, + AvailTC p [name]) lookup_ie ie@(IEThingAll rdr) = do name <- lookupGlobalOccRn rdr @@ -921,13 +907,23 @@ check_occs ie occs names %********************************************************* \begin{code} -reportDeprecations :: DynFlags -> TcGblEnv -> RnM () -reportDeprecations dflags tcg_env - = ifOptM Opt_WarnDeprecations $ - do { (eps,hpt) <- getEpsAndHpt +finishDeprecations :: DynFlags -> Maybe DeprecTxt + -> TcGblEnv -> RnM TcGblEnv +-- (a) Report usasge of deprecated imports +-- (b) If the whole module is deprecated, update tcg_deprecs +-- All this happens only once per module +finishDeprecations dflags mod_deprec tcg_env + = do { (eps,hpt) <- getEpsAndHpt + ; ifOptM Opt_WarnDeprecations $ + mapM_ (check hpt (eps_PIT eps)) all_gres -- By this time, typechecking is complete, -- so the PIT is fully populated - ; mapM_ (check hpt (eps_PIT eps)) all_gres } + + -- Deal with a module deprecation; it overrides all existing deprecs + ; let new_deprecs = case mod_deprec of + Just txt -> DeprecAll txt + Nothing -> tcg_deprecs tcg_env + ; return (tcg_env { tcg_deprecs = new_deprecs }) } where used_names = allUses (tcg_dus tcg_env) -- Report on all deprecated uses; hence allUses @@ -935,7 +931,7 @@ reportDeprecations dflags tcg_env check hpt pit gre@(GRE {gre_name = name, gre_prov = Imported (imp_spec:_)}) | name `elemNameSet` used_names - , Just deprec_txt <- lookupDeprec dflags hpt pit gre + , Just deprec_txt <- lookupImpDeprec dflags hpt pit gre = addWarnAt (importSpecLoc imp_spec) (sep [ptext SLIT("Deprecated use of") <+> pprNonVarNameSpace (occNameSpace (nameOccName name)) <+> @@ -957,26 +953,43 @@ reportDeprecations dflags tcg_env -- the defn of a non-deprecated thing, when changing a module's -- interface -lookupDeprec :: DynFlags -> HomePackageTable -> PackageIfaceTable - -> GlobalRdrElt -> Maybe DeprecTxt -lookupDeprec dflags hpt pit gre +lookupImpDeprec :: DynFlags -> HomePackageTable -> PackageIfaceTable + -> GlobalRdrElt -> Maybe DeprecTxt +-- The name is definitely imported, so look in HPT, PIT +lookupImpDeprec dflags hpt pit gre = case lookupIfaceByModule dflags hpt pit (nameModule name) of Just iface -> mi_dep_fn iface name `seqMaybe` -- Bleat if the thing, *or case gre_par gre of ParentIs p -> mi_dep_fn iface p -- its parent*, is deprec'd NoParent -> Nothing - Nothing - | isWiredInName name -> Nothing - -- We have not necessarily loaded the .hi file for a - -- wired-in name (yet), although we *could*. - -- And we never deprecate them - - | otherwise -> pprPanic "lookupDeprec" (ppr name) - -- By now all the interfaces should have been loaded + + Nothing -> Nothing -- See Note [Used names with interface not loaded] where name = gre_name gre \end{code} +Note [Used names with interface not loaded] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +By now all the interfaces should have been loaded, +because reportDeprecations happens after typechecking. +However, it's still (just) possible to to find a used +Name whose interface hasn't been loaded: + +a) It might be a WiredInName; in that case we may not load + its interface (although we could). + +b) It might be GHC.Real.fromRational, or GHC.Num.fromInteger + These are seen as "used" by the renamer (if -fno-implicit-prelude) + is on), but the typechecker may discard their uses + if in fact the in-scope fromRational is GHC.Read.fromRational, + (see tcPat.tcOverloadedLit), and the typechecker sees that the type + is fixed, say, to GHC.Base.Float (see Inst.lookupSimpleInst). + In that obscure case it won't force the interface in. + +In both cases we simply don't permit deprecations; +this is, after all, wired-in stuff. + + %********************************************************* %* * Unused names @@ -1029,14 +1042,15 @@ reportUnusedNames export_decls gbl_env is_unused_local :: GlobalRdrElt -> Bool is_unused_local gre = isLocalGRE gre && isExternalName (gre_name gre) - unused_imports :: [GlobalRdrElt] - unused_imports = filter unused_imp defined_but_not_used - unused_imp (GRE {gre_prov = Imported imp_specs}) - = not (all (module_unused . importSpecModule) imp_specs) - && or [exp | ImpSpec { is_item = ImpSome { is_explicit = exp } } <- imp_specs] - -- Don't complain about unused imports if we've already said the - -- entire import is unused - unused_imp other = False + unused_imports :: [GlobalRdrElt] + unused_imports = mapCatMaybes unused_imp defined_but_not_used + unused_imp :: GlobalRdrElt -> Maybe GlobalRdrElt -- Result has trimmed Imported provenances + unused_imp gre@(GRE {gre_prov = LocalDef}) = Nothing + unused_imp gre@(GRE {gre_prov = Imported imp_specs}) + | null trimmed_specs = Nothing + | otherwise = Just (gre {gre_prov = Imported trimmed_specs}) + where + trimmed_specs = filter report_if_unused imp_specs -- To figure out the minimal set of imports, start with the things -- that are in scope (i.e. in gbl_env). Then just combine them @@ -1112,6 +1126,7 @@ reportUnusedNames export_decls gbl_env -- -- BUG WARNING: does not deal correctly with multiple imports of the same module -- becuase direct_import_mods has only one entry per module + unused_imp_mods :: [(ModuleName, SrcSpan)] unused_imp_mods = [(mod_name,loc) | (mod,no_imp,loc) <- direct_import_mods, let mod_name = moduleName mod, not (mod_name `elemFM` minimal_imports1), @@ -1124,6 +1139,12 @@ reportUnusedNames export_decls gbl_env module_unused :: ModuleName -> Bool module_unused mod = any (((==) mod) . fst) unused_imp_mods + report_if_unused :: ImportSpec -> Bool + -- Do we want to report this as an unused import? + report_if_unused (ImpSpec {is_decl = d, is_item = i}) + = not (module_unused (is_mod d)) -- Not if we've already said entire import is unused + && isExplicitItem i -- Only if the import was explicit + --------------------- warnDuplicateImports :: [GlobalRdrElt] -> RnM () -- Given the GREs for names that are used, figure out which imports @@ -1142,8 +1163,6 @@ warnDuplicateImports :: [GlobalRdrElt] -> RnM () warnDuplicateImports gres = ifOptM Opt_WarnUnusedImports $ sequenceM_ [ warn name pr - -- The 'head' picks the first offending group - -- for this particular name | GRE { gre_name = name, gre_prov = Imported imps } <- gres , pr <- redundants imps ] where @@ -1162,7 +1181,12 @@ warnDuplicateImports gres redundants imps = [ (red_imp, cov_imp) | red_imp <- imps + , isExplicitItem (is_item red_imp) + -- Complain only about redundant imports + -- mentioned explicitly by the user , cov_imp <- take 1 (filter (covers red_imp) imps) ] + -- The 'take 1' picks the first offending group + -- for this particular name -- "red_imp" is a putative redundant import -- "cov_imp" potentially covers it @@ -1183,6 +1207,10 @@ warnDuplicateImports gres = False -- They bring into scope different qualified names | not (is_qual red_decl) && is_qual cov_decl = False -- Covering one doesn't bring unqualified name into scope + | otherwise + = not (isExplicitItem cov_item) -- Redundant one is selective and covering one isn't + || red_later -- or both are explicit; tie-break using red_later +{- | red_selective = not cov_selective -- Redundant one is selective and covering one isn't || red_later -- Both are explicit; tie-break using red_later @@ -1190,16 +1218,11 @@ warnDuplicateImports gres = not cov_selective -- Neither import is selective && (is_mod red_decl == is_mod cov_decl) -- They import the same module && red_later -- Tie-break +-} where red_loc = importSpecLoc red_imp cov_loc = importSpecLoc cov_imp red_later = red_loc > cov_loc - cov_selective = selectiveImpItem cov_item - red_selective = selectiveImpItem red_item - -selectiveImpItem :: ImpItemSpec -> Bool -selectiveImpItem ImpAll = False -selectiveImpItem (ImpSome {}) = True -- ToDo: deal with original imports with 'qualified' and 'as M' clauses printMinimalImports :: FiniteMap ModuleName AvailEnv -- Minimal imports @@ -1207,7 +1230,7 @@ printMinimalImports :: FiniteMap ModuleName AvailEnv -- Minimal imports printMinimalImports imps = ifOptM Opt_D_dump_minimal_imports $ do { - mod_ies <- mappM to_ies (fmToList imps) ; + mod_ies <- initIfaceTcRn $ mappM to_ies (fmToList imps) ; this_mod <- getModule ; rdr_env <- getGlobalRdrEnv ; ioToTcRn (do { h <- openFile (mkFilename this_mod) WriteMode ; @@ -1228,7 +1251,7 @@ printMinimalImports imps to_ies (mod, avail_env) = do ies <- mapM to_ie (availEnvElts avail_env) returnM (mod, ies) - to_ie :: AvailInfo -> RnM (IE Name) + to_ie :: AvailInfo -> IfG (IE Name) -- The main trick here is that if we're importing all the constructors -- we want to say "T(..)", but if we're importing only a subset we want -- to say "T(A,B,C)". So we have to find out what the module exports. @@ -1236,9 +1259,9 @@ printMinimalImports imps to_ie (AvailTC n [m]) = ASSERT( n==m ) returnM (IEThingAbs n) to_ie (AvailTC n ns) - = loadSrcInterface doc n_mod False `thenM` \ iface -> + = loadSysInterface doc n_mod `thenM` \ iface -> case [xs | (m,as) <- mi_exports iface, - moduleName m == n_mod, + m == n_mod, AvailTC x xs <- as, x == nameOccName n] of [xs] | all_used xs -> returnM (IEThingAll n) @@ -1248,7 +1271,7 @@ printMinimalImports imps where all_used avail_occs = all (`elem` map nameOccName ns) avail_occs doc = text "Compute minimal imports from" <+> ppr n - n_mod = moduleName (nameModule n) + n_mod = nameModule n \end{code}