[commit: ghc] master: Fix AMP warnings for explicit Prelude imports (#8004) (b9127f4)
git at git.haskell.org
git at git.haskell.org
Mon Sep 30 03:10:16 CEST 2013
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/b9127f4472594e8d0c2f28f72b6042172efcaec0/ghc
>---------------------------------------------------------------
commit b9127f4472594e8d0c2f28f72b6042172efcaec0
Author: Austin Seipp <austin at well-typed.com>
Date: Sun Sep 29 18:12:13 2013 -0500
Fix AMP warnings for explicit Prelude imports (#8004)
No AMP warnings will be issued anymore when the name is not imported
from Prelude anymore. For example, a local definition of 'join' is now
legal in modules containing 'import Prelude (map)' for example. This
allows better future-proofing of libraries.
See also http://ghc.haskell.org/trac/ghc/ticket/8004#comment:16
Authored-by: David Luposchainsky <dluposchainsky at gmail.com>
Signed-off-by: Austin Seipp <austin at well-typed.com>
>---------------------------------------------------------------
b9127f4472594e8d0c2f28f72b6042172efcaec0
compiler/typecheck/TcRnDriver.lhs | 72 +++++++++++++++++++++++++++++++++----
1 file changed, 66 insertions(+), 6 deletions(-)
diff --git a/compiler/typecheck/TcRnDriver.lhs b/compiler/typecheck/TcRnDriver.lhs
index a88daa8..6b502fe 100644
--- a/compiler/typecheck/TcRnDriver.lhs
+++ b/compiler/typecheck/TcRnDriver.lhs
@@ -945,16 +945,26 @@ tcAmpWarn =
-- | Warn on local definitions of names that would clash with Prelude versions,
-- i.e. join/pure/<*>
+--
+-- A name clashes if the following criteria are met:
+-- 1. It would is imported (unqualified) from Prelude
+-- 2. It is locally defined in the current module
+-- 3. It has the same literal name as the reference function
+-- 4. It is not identical to the reference function
tcAmpFunctionWarn :: Name -- ^ Name to check, e.g. joinMName for join
-> TcM ()
tcAmpFunctionWarn name = do
+ { traceTc "tcAmpFunctionWarn/wouldBeImported" empty
+ -- Is the name imported (unqualified) from Prelude? (Point 4 above)
+ ; rnImports <- fmap (map unLoc . tcg_rn_imports) getGblEnv
+ -- (Note that this automatically handles -XNoImplicitPrelude, as Prelude
+ -- will not appear in rnImports automatically if it is set.)
+
+ -- Continue only the name is imported from Prelude
+ ; when (tcAmpImportViaPrelude name rnImports) $ do
+ -- Handle 2.-4.
{ rdrElts <- fmap (concat . occEnvElts . tcg_rdr_env) getGblEnv
- -- Finds *other* elements having the same literal name. A name clashes
- -- iff:
- -- 1. It is locally defined in the current module
- -- 2. It has the same literal name as the reference function
- -- 3. It is not identical to the reference function
; let clashes :: GlobalRdrElt -> Bool
clashes x = and [ gre_prov x == LocalDef
, nameOccName (gre_name x) == nameOccName name
@@ -976,7 +986,57 @@ tcAmpFunctionWarn name = do
, ptext (sLit "under the Applicative-Monad Proposal.")
]
; mapM_ warn_msg clashingElts
- }
+ }}
+
+-- | Is the given name imported via Prelude?
+--
+-- This function makes sure that e.g. "import Prelude (map)" should silence
+-- AMP warnings about "join" even when they are locally defined.
+--
+-- Possible scenarios:
+-- a) Prelude is imported implicitly, issue warnings.
+-- b) Prelude is imported explicitly, but without mentioning the name in
+-- question. Issue no warnings.
+-- c) Prelude is imported hiding the name in question. Issue no warnings.
+-- d) Qualified import of Prelude, no warnings.
+tcAmpImportViaPrelude :: Name
+ -> [ImportDecl Name]
+ -> Bool
+tcAmpImportViaPrelude name = any importViaPrelude
+ where
+ isPrelude :: ImportDecl Name -> Bool
+ isPrelude = (== "Prelude") . moduleNameString . unLoc . ideclName
+
+ -- Implicit (Prelude) import?
+ isImplicit :: ImportDecl Name -> Bool
+ isImplicit = ideclImplicit
+
+ -- Unqualified import?
+ isUnqualified :: ImportDecl Name -> Bool
+ isUnqualified = not . ideclQualified
+
+ second :: (a -> b) -> (x, a) -> (x, b)
+ second f (x, y) = (x, f y)
+
+ -- List of explicitly imported (or hidden) Names from a single import.
+ -- Nothing -> No explicit imports
+ -- Just (False, <names>) -> Explicit import list of <names>
+ -- Just (True , <names>) -> Explicit hiding of <names>
+ importList :: ImportDecl Name -> Maybe (Bool, [Name])
+ importList = fmap (second (map (ieName . unLoc))) . ideclHiding
+
+ -- Check whether the given name would be imported (unqualified) from
+ -- an import declaration.
+ importViaPrelude :: ImportDecl Name -> Bool
+ importViaPrelude x = isPrelude x && isUnqualified x && or [
+ -- Whole Prelude imported -> potential clash
+ isImplicit x
+ -- Explicit import/hiding list, if applicable
+ , case importList x of
+ Just (False, explicit) -> nameOccName name `elem` map nameOccName explicit
+ Just (True , hidden ) -> nameOccName name `notElem` map nameOccName hidden
+ Nothing -> False
+ ]
-- | Issue a warning for instance definitions lacking a should-be parent class.
-- Used for Monad without Applicative and MonadPlus without Alternative.
More information about the ghc-commits
mailing list