Commit bcff115a authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Report deprecations at occurrence sites, not once per module

Fixes Trac #5867, and is generally nicer
parent aaff8766
......@@ -63,7 +63,7 @@ import Control.Monad
%************************************************************************
%* *
loadSrcInterface, loadOrphanModules, loadHomeInterface
loadSrcInterface, loadOrphanModules, loadInterfaceForName
These three are called from TcM-land
%* *
......
......@@ -663,28 +663,111 @@ lookupGreRn_help rdr_name lookup
; return (Just gre) }
gres -> do { addNameClashErrRn rdr_name gres
; return (Just (head gres)) } }
\end{code}
%*********************************************************
%* *
Deprecations
%* *
%*********************************************************
Note [Handling of deprecations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* We report deprecations at each *occurrence* of the deprecated thing
(see Trac #5867)
* We do not report deprectations for locally-definded names. For a
start, we may be exporting a deprecated thing. Also we may use a
deprecated thing in the defn of another deprecated things. We may
even use a deprecated thing in the defn of a non-deprecated thing,
when changing a module's interface.
* addUsedRdrNames: we do not report deprecations for sub-binders:
- the ".." completion for records
- the ".." in an export item 'T(..)'
- the things exported by a module export 'module M'
\begin{code}
addUsedRdrName :: GlobalRdrElt -> RdrName -> RnM ()
-- Record usage of imported RdrNames
addUsedRdrName gre rdr
| isLocalGRE gre = return ()
| isLocalGRE gre = return () -- No call to warnIfDeprecated
-- See Note [Handling of deprecations]
| otherwise = do { env <- getGblEnv
; updMutVar (tcg_used_rdrnames env)
; warnIfDeprecated gre
; updMutVar (tcg_used_rdrnames env)
(\s -> Set.insert rdr s) }
addUsedRdrNames :: [RdrName] -> RnM ()
-- Record used sub-binders
-- We don't check for imported-ness here, because it's inconvenient
-- and not stritly necessary.
-- NB: no call to warnIfDeprecated; see Note [Handling of deprecations]
addUsedRdrNames rdrs
= do { env <- getGblEnv
; updMutVar (tcg_used_rdrnames env)
(\s -> foldr Set.insert s rdrs) }
------------------------------
-- GHCi support
------------------------------
warnIfDeprecated :: GlobalRdrElt -> RnM ()
warnIfDeprecated gre@(GRE { gre_name = name, gre_prov = Imported (imp_spec : _) })
= do { dflags <- getDynFlags
; when (wopt Opt_WarnWarningsDeprecations dflags) $
do { iface <- loadInterfaceForName doc name
; case lookupImpDeprec iface gre of
Just txt -> addWarn (mk_msg txt)
Nothing -> return () } }
where
mk_msg txt = sep [ sep [ ptext (sLit "In the use of")
<+> pprNonVarNameSpace (occNameSpace (nameOccName name))
<+> quotes (ppr name)
, parens imp_msg <> colon ]
, ppr txt ]
name_mod = ASSERT2( isExternalName name, ppr name ) nameModule name
imp_mod = importSpecModule imp_spec
imp_msg = ptext (sLit "imported from") <+> ppr imp_mod <> extra
extra | imp_mod == moduleName name_mod = empty
| otherwise = ptext (sLit ", but defined in") <+> ppr name_mod
doc = ptext (sLit "The name") <+> quotes (ppr name) <+> ptext (sLit "is mentioned explicitly")
warnIfDeprecated _ = return () -- No deprecations for things defined locally
lookupImpDeprec :: ModIface -> GlobalRdrElt -> Maybe WarningTxt
lookupImpDeprec iface gre
= mi_warn_fn iface (gre_name gre) `mplus` -- Bleat if the thing,
case gre_par gre of -- *or its parent*, is warn'd
ParentIs p -> mi_warn_fn iface p
NoParent -> Nothing
\end{code}
Note [Used names with interface not loaded]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's (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 -XRebindableSyntax)
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.
%*********************************************************
%* *
GHCi support
%* *
%*********************************************************
\begin{code}
-- A qualified name on the command line can refer to any module at all: we
-- try to load the interface if we don't already have it.
lookupQualifiedName :: RdrName -> RnM (Maybe Name)
......
......@@ -8,7 +8,7 @@ module RnNames (
rnImports, getLocalNonValBinders,
rnExports, extendGlobalRdrEnvRn,
gresFromAvails,
reportUnusedNames, finishWarnings,
reportUnusedNames,
) where
#include "HsVersions.h"
......@@ -904,7 +904,11 @@ rnExports explicit_mod exports
tcg_env@(TcGblEnv { tcg_mod = this_mod,
tcg_rdr_env = rdr_env,
tcg_imports = imports })
= do {
= unsetWOptM Opt_WarnWarningsDeprecations $
-- Do not report deprecations arising from the export
-- list, to avoid bleating about re-exporting a deprecated
-- thing (especially via 'module Foo' export item)
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
......@@ -1175,96 +1179,6 @@ dupExport_ok n ie1 ie2
single _ = False
\end{code}
%*********************************************************
%* *
\subsection{Deprecations}
%* *
%*********************************************************
\begin{code}
finishWarnings :: DynFlags -> Maybe WarningTxt
-> TcGblEnv -> RnM TcGblEnv
-- (a) Report usage of imports that are deprecated or have other warnings
-- (b) If the whole module is warned about or deprecated, update tcg_warns
-- All this happens only once per module
finishWarnings dflags mod_warn tcg_env
= do { (eps,hpt) <- getEpsAndHpt
; ifWOptM Opt_WarnWarningsDeprecations $
mapM_ (check hpt (eps_PIT eps)) all_gres
-- By this time, typechecking is complete,
-- so the PIT is fully populated
-- Deal with a module deprecation; it overrides all existing warns
; let new_warns = case mod_warn of
Just txt -> WarnAll txt
Nothing -> tcg_warns tcg_env
; return (tcg_env { tcg_warns = new_warns }) }
where
used_names = allUses (tcg_dus tcg_env)
-- Report on all deprecated uses; hence allUses
all_gres = globalRdrEnvElts (tcg_rdr_env tcg_env)
check hpt pit gre@(GRE {gre_name = name, gre_prov = Imported (imp_spec:_)})
| name `elemNameSet` used_names
, Just deprec_txt <- lookupImpDeprec dflags hpt pit gre
= addWarnAt (importSpecLoc imp_spec)
(sep [ptext (sLit "In the use of") <+>
pprNonVarNameSpace (occNameSpace (nameOccName name)) <+>
quotes (ppr name),
(parens imp_msg) <> colon,
(ppr deprec_txt) ])
where
name_mod = ASSERT2( isExternalName name, ppr name ) nameModule name
imp_mod = importSpecModule imp_spec
imp_msg = ptext (sLit "imported from") <+> ppr imp_mod <> extra
extra | imp_mod == moduleName name_mod = empty
| otherwise = ptext (sLit ", but defined in") <+> ppr name_mod
check _ _ _ = return () -- Local, or not used, or not deprectated
-- The Imported pattern-match: don't deprecate locally defined names
-- For a start, we may be exporting a deprecated thing
-- Also we may use a deprecated thing in the defn of another
-- deprecated things. We may even use a deprecated thing in
-- the defn of a non-deprecated thing, when changing a module's
-- interface
lookupImpDeprec :: DynFlags -> HomePackageTable -> PackageIfaceTable
-> GlobalRdrElt -> Maybe WarningTxt
-- The name is definitely imported, so look in HPT, PIT
lookupImpDeprec dflags hpt pit gre
= case lookupIfaceByModule dflags hpt pit mod of
Just iface -> mi_warn_fn iface name `mplus` -- Bleat if the thing, *or
case gre_par gre of
ParentIs p -> mi_warn_fn iface p -- its parent*, is warn'd
NoParent -> Nothing
Nothing -> Nothing -- See Note [Used names with interface not loaded]
where
name = gre_name gre
mod = ASSERT2( isExternalName name, ppr name ) nameModule name
\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 -XRebindableSyntax)
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.
%*********************************************************
%* *
......
......@@ -150,7 +150,16 @@ tcRnModule hsc_env hsc_src save_rn_syntax
tcg_env <- {-# SCC "tcRnImports" #-}
tcRnImports hsc_env this_mod (prel_imports ++ import_decls) ;
setGblEnv tcg_env $ do {
-- If the whole module is warned about or deprecated
-- (via mod_deprec) record that in tcg_warns. If we do thereby add
-- a WarnAll, it will override any subseqent depracations added to tcg_warns
let { tcg_env1 = case mod_deprec of
Just txt -> tcg_env { tcg_warns = WarnAll txt }
Nothing -> tcg_env
} ;
setGblEnv tcg_env1 $ do {
-- Load the hi-boot interface for this module, if any
-- We do this now so that the boot_names can be passed
......@@ -171,16 +180,6 @@ tcRnModule hsc_env hsc_src save_rn_syntax
tcRnSrcDecls boot_iface local_decls ;
setGblEnv tcg_env $ do {
-- Report the use of any deprecated things
-- We do this *before* processsing the export list so
-- that we don't bleat about re-exporting a deprecated
-- thing (especially via 'module Foo' export item)
-- That is, only uses in the *body* of the module are complained about
traceRn (text "rn3") ;
failIfErrsM ; -- finishWarnings crashes sometimes
-- as a result of typechecker repairs (e.g. unboundNames)
tcg_env <- finishWarnings (hsc_dflags hsc_env) mod_deprec tcg_env ;
-- Process the export list
traceRn (text "rn4a: before exports");
tcg_env <- rnExports (isJust maybe_mod) export_ies tcg_env ;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment