Refactor SrcLoc and SrcSpan
[ghc-hetmet.git] / compiler / rename / RnEnv.lhs
index 20d2218..b333373 100644 (file)
@@ -8,27 +8,26 @@ module RnEnv (
        newTopSrcBinder, lookupFamInstDeclBndr,
        lookupLocatedTopBndrRn, lookupTopBndrRn,
        lookupLocatedOccRn, lookupOccRn, 
        newTopSrcBinder, lookupFamInstDeclBndr,
        lookupLocatedTopBndrRn, lookupTopBndrRn,
        lookupLocatedOccRn, lookupOccRn, 
-       lookupLocatedGlobalOccRn, 
-       lookupGlobalOccRn, lookupGlobalOccRn_maybe,
+        lookupGlobalOccRn, lookupGlobalOccRn_maybe,
        lookupLocalDataTcNames, lookupSigOccRn,
        lookupFixityRn, lookupTyFixityRn, 
        lookupInstDeclBndr, lookupSubBndr, lookupConstructorFields,
        lookupLocalDataTcNames, lookupSigOccRn,
        lookupFixityRn, lookupTyFixityRn, 
        lookupInstDeclBndr, lookupSubBndr, lookupConstructorFields,
-       lookupSyntaxName, lookupSyntaxTable, 
+       lookupSyntaxName, lookupSyntaxTable, lookupIfThenElse,
        lookupGreRn, lookupGreLocalRn, lookupGreRn_maybe,
        getLookupOccRn, addUsedRdrNames,
 
        newLocalBndrRn, newLocalBndrsRn, newIPNameRn,
        bindLocalName, bindLocalNames, bindLocalNamesFV, 
        MiniFixityEnv, emptyFsEnv, extendFsEnv, lookupFsEnv,
        lookupGreRn, lookupGreLocalRn, lookupGreRn_maybe,
        getLookupOccRn, addUsedRdrNames,
 
        newLocalBndrRn, newLocalBndrsRn, newIPNameRn,
        bindLocalName, bindLocalNames, bindLocalNamesFV, 
        MiniFixityEnv, emptyFsEnv, extendFsEnv, lookupFsEnv,
-       bindLocalNamesFV_WithFixities,
+       addLocalFixities,
        bindLocatedLocalsFV, bindLocatedLocalsRn,
        bindSigTyVarsFV, bindPatSigTyVars, bindPatSigTyVarsFV,
        bindLocatedLocalsFV, bindLocatedLocalsRn,
        bindSigTyVarsFV, bindPatSigTyVars, bindPatSigTyVarsFV,
-       bindTyVarsRn, extendTyVarEnvFVRn,
+       bindTyVarsRn, bindTyVarsFV, extendTyVarEnvFVRn,
 
 
-       checkDupRdrNames, checkDupNames, checkShadowedNames, 
-       checkDupAndShadowedRdrNames,
-       mapFvRn, mapFvRnCPS,
-       warnUnusedMatches, warnUnusedModules, warnUnusedImports, 
+       checkDupRdrNames, checkDupAndShadowedRdrNames,
+        checkDupNames, checkDupAndShadowedNames, 
+       addFvRn, mapFvRn, mapMaybeFvRn, mapFvRnCPS,
+       warnUnusedMatches,
        warnUnusedTopBinds, warnUnusedLocalBinds,
        dataTcOccs, unknownNameErr, kindSigErr, perhapsForallMsg
     ) where
        warnUnusedTopBinds, warnUnusedLocalBinds,
        dataTcOccs, unknownNameErr, kindSigErr, perhapsForallMsg
     ) where
@@ -44,16 +43,13 @@ import HscTypes             ( availNames, ModIface(..), FixItem(..), lookupFixity)
 import TcEnv           ( tcLookupDataCon, tcLookupField, isBrackStage )
 import TcRnMonad
 import Id              ( isRecordSelector )
 import TcEnv           ( tcLookupDataCon, tcLookupField, isBrackStage )
 import TcRnMonad
 import Id              ( isRecordSelector )
-import Name            ( Name, nameIsLocalOrFrom, mkInternalName, isWiredInName,
-                         nameSrcLoc, nameSrcSpan, nameOccName, nameModule, isExternalName )
+import Name
 import NameSet
 import NameEnv
 import NameSet
 import NameEnv
-import LazyUniqFM
+import Module           ( ModuleName, moduleName )
+import UniqFM
 import DataCon         ( dataConFieldLabels )
 import DataCon         ( dataConFieldLabels )
-import OccName
-import Module          ( Module, ModuleName )
-import PrelNames       ( mkUnboundName, rOOT_MAIN, iNTERACTIVE, 
-                         consDataConKey, forall_tv_RDR )
+import PrelNames        ( mkUnboundName, rOOT_MAIN, consDataConKey, forall_tv_RDR )
 import Unique
 import BasicTypes
 import ErrUtils                ( Message )
 import Unique
 import BasicTypes
 import ErrUtils                ( Message )
@@ -82,8 +78,8 @@ thenM = (>>=)
 %*********************************************************
 
 \begin{code}
 %*********************************************************
 
 \begin{code}
-newTopSrcBinder :: Module -> Located RdrName -> RnM Name
-newTopSrcBinder this_mod (L loc rdr_name)
+newTopSrcBinder :: Located RdrName -> RnM Name
+newTopSrcBinder (L loc rdr_name)
   | Just name <- isExact_maybe rdr_name
   =    -- This is here to catch 
        --   (a) Exact-name binders created by Template Haskell
   | Just name <- isExact_maybe rdr_name
   =    -- This is here to catch 
        --   (a) Exact-name binders created by Template Haskell
@@ -95,13 +91,15 @@ newTopSrcBinder this_mod (L loc rdr_name)
        --      data T = (,) Int Int
        -- unless we are in GHC.Tup
     ASSERT2( isExternalName name,  ppr name )
        --      data T = (,) Int Int
        -- unless we are in GHC.Tup
     ASSERT2( isExternalName name,  ppr name )
-    do { unless (this_mod == nameModule name)
+    do { this_mod <- getModule
+        ; unless (this_mod == nameModule name)
                 (addErrAt loc (badOrigBinding rdr_name))
        ; return name }
 
 
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
                 (addErrAt loc (badOrigBinding rdr_name))
        ; return name }
 
 
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
-  = do { unless (rdr_mod == this_mod || rdr_mod == rOOT_MAIN)
+  = do { this_mod <- getModule
+        ; unless (rdr_mod == this_mod || rdr_mod == rOOT_MAIN)
                 (addErrAt loc (badOrigBinding rdr_name))
        -- When reading External Core we get Orig names as binders, 
        -- but they should agree with the module gotten from the monad
                 (addErrAt loc (badOrigBinding rdr_name))
        -- When reading External Core we get Orig names as binders, 
        -- but they should agree with the module gotten from the monad
@@ -137,7 +135,8 @@ newTopSrcBinder this_mod (L loc rdr_name)
                ; return (mkInternalName uniq (rdrNameOcc rdr_name) loc) } 
          else  
                -- Normal case
                ; return (mkInternalName uniq (rdrNameOcc rdr_name) loc) } 
          else  
                -- Normal case
-            newGlobalBinder this_mod (rdrNameOcc rdr_name) loc }
+             do { this_mod <- getModule
+                ; newGlobalBinder this_mod (rdrNameOcc rdr_name) loc } }
 \end{code}
 
 %*********************************************************
 \end{code}
 
 %*********************************************************
@@ -166,7 +165,7 @@ lookupTopBndrRn n = do nopt <- lookupTopBndrRn_maybe n
                        case nopt of 
                          Just n' -> return n'
                          Nothing -> do traceRn $ text "lookupTopBndrRn"
                        case nopt of 
                          Just n' -> return n'
                          Nothing -> do traceRn $ text "lookupTopBndrRn"
-                                       unboundName n
+                                       unboundName WL_LocalTop n
 
 lookupLocatedTopBndrRn :: Located RdrName -> RnM (Located Name)
 lookupLocatedTopBndrRn = wrapLocM lookupTopBndrRn
 
 lookupLocatedTopBndrRn :: Located RdrName -> RnM (Located Name)
 lookupLocatedTopBndrRn = wrapLocM lookupTopBndrRn
@@ -205,7 +204,7 @@ lookupTopBndrRn_maybe rdr_name
            -- See Note [Type and class operator definitions]
           let occ = rdrNameOcc rdr_name
         ; when (isTcOcc occ && isSymOcc occ)
            -- See Note [Type and class operator definitions]
           let occ = rdrNameOcc rdr_name
         ; when (isTcOcc occ && isSymOcc occ)
-               (do { op_ok <- doptM Opt_TypeOperators
+               (do { op_ok <- xoptM Opt_TypeOperators
                   ; unless op_ok (addErr (opDeclErr rdr_name)) })
 
        ; mb_gre <- lookupGreLocalRn rdr_name
                   ; unless op_ok (addErr (opDeclErr rdr_name)) })
 
        ; mb_gre <- lookupGreLocalRn rdr_name
@@ -284,12 +283,12 @@ lookupSubBndr parent doc rdr_name
   | otherwise  -- Find all the things the rdr-name maps to
   = do {       -- and pick the one with the right parent name
        ; env <- getGlobalRdrEnv
   | otherwise  -- Find all the things the rdr-name maps to
   = do {       -- and pick the one with the right parent name
        ; env <- getGlobalRdrEnv
-        ; let gres = (lookupGlobalRdrEnv env (rdrNameOcc rdr_name))
+        ; let gres = lookupGlobalRdrEnv env (rdrNameOcc rdr_name)
        ; case pick parent gres  of
                -- NB: lookupGlobalRdrEnv, not lookupGRE_RdrName!
                --     The latter does pickGREs, but we want to allow 'x'
                --     even if only 'M.x' is in scope
        ; case pick parent gres  of
                -- NB: lookupGlobalRdrEnv, not lookupGRE_RdrName!
                --     The latter does pickGREs, but we want to allow 'x'
                --     even if only 'M.x' is in scope
-           [gre] -> do { addUsedRdrName gre rdr_name
+           [gre] -> do { addUsedRdrNames (used_rdr_names gre)
                         ; return (gre_name gre) }
            []    -> do { addErr (unknownSubordinateErr doc rdr_name)
                        ; traceRn (text "RnEnv.lookup_sub_bndr" <+> (ppr rdr_name $$ ppr gres))
                         ; return (gre_name gre) }
            []    -> do { addErr (unknownSubordinateErr doc rdr_name)
                        ; traceRn (text "RnEnv.lookup_sub_bndr" <+> (ppr rdr_name $$ ppr gres))
@@ -306,6 +305,15 @@ lookupSubBndr parent doc rdr_name
     right_parent p (GRE { gre_par = ParentIs p' }) = p==p' 
     right_parent _ _                               = False
 
     right_parent p (GRE { gre_par = ParentIs p' }) = p==p' 
     right_parent _ _                               = False
 
+    -- Note [Usage for sub-bndrs]
+    used_rdr_names gre
+      | isQual rdr_name = [rdr_name]
+      | otherwise       = case gre_prov gre of
+                            LocalDef -> [rdr_name]
+                           Imported is -> map mk_qual_rdr is
+    mk_qual_rdr imp_spec = mkRdrQual (is_as (is_decl imp_spec)) rdr_occ
+    rdr_occ = rdrNameOcc rdr_name    
+
 newIPNameRn :: IPName RdrName -> TcRnIf m n (IPName Name)
 newIPNameRn ip_rdr = newIPName (mapIPName rdrNameOcc ip_rdr)
 
 newIPNameRn :: IPName RdrName -> TcRnIf m n (IPName Name)
 newIPNameRn ip_rdr = newIPName (mapIPName rdrNameOcc ip_rdr)
 
@@ -320,12 +328,25 @@ lookupFamInstDeclBndr tyclGroupEnv (L loc rdr_name)
         (gre:_) -> return $ gre_name gre
           -- if there is more than one, an error will be raised elsewhere
         []      -> lookupOccRn rdr_name
         (gre:_) -> return $ gre_name gre
           -- if there is more than one, an error will be raised elsewhere
         []      -> lookupOccRn rdr_name
+\end{code}
 
 
+Note [Usage for sub-bndrs]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you have this
+   import qualified M( C( f ) ) 
+   intance M.C T where
+     f x = x
+then is the qualified import M.f used?  Obviously yes.
+But the RdrName used in the instance decl is unqualified.  In effect,
+we fill in the qualification by looking for f's whose class is M.C
+But when adding to the UsedRdrNames we must make that qualification
+explicit, otherwise we get "Redundant import of M.C".
 
 --------------------------------------------------
 --             Occurrences
 --------------------------------------------------
 
 
 --------------------------------------------------
 --             Occurrences
 --------------------------------------------------
 
+\begin{code}
 getLookupOccRn :: RnM (Name -> Maybe Name)
 getLookupOccRn
   = getLocalRdrEnv                     `thenM` \ local_env ->
 getLookupOccRn :: RnM (Name -> Maybe Name)
 getLookupOccRn
   = getLocalRdrEnv                     `thenM` \ local_env ->
@@ -337,22 +358,12 @@ lookupLocatedOccRn = wrapLocM lookupOccRn
 -- lookupOccRn looks up an occurrence of a RdrName
 lookupOccRn :: RdrName -> RnM Name
 lookupOccRn rdr_name
 -- lookupOccRn looks up an occurrence of a RdrName
 lookupOccRn :: RdrName -> RnM Name
 lookupOccRn rdr_name
-  = getLocalRdrEnv                     `thenM` \ local_env ->
-    case lookupLocalRdrEnv local_env rdr_name of
-         Just name -> return name
-         Nothing   -> lookupGlobalOccRn rdr_name
-
-lookupLocatedGlobalOccRn :: Located RdrName -> RnM (Located Name)
-lookupLocatedGlobalOccRn = wrapLocM lookupGlobalOccRn
+  = do { local_env <- getLocalRdrEnv
+       ; case lookupLocalRdrEnv local_env rdr_name of {
+          Just name -> return name ;
+          Nothing   -> do
 
 
-lookupGlobalOccRn :: RdrName -> RnM Name
--- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
--- environment.  Adds an error message if the RdrName is not in scope.
--- Also has a special case for GHCi.
-
-lookupGlobalOccRn rdr_name
-  = do { -- First look up the name in the normal environment.
-         mb_name <- lookupGlobalOccRn_maybe rdr_name
+       { mb_name <- lookupGlobalOccRn_maybe rdr_name
        ; case mb_name of {
                Just n  -> return n ;
                Nothing -> do
        ; case mb_name of {
                Just n  -> return n ;
                Nothing -> do
@@ -361,12 +372,22 @@ lookupGlobalOccRn rdr_name
         --  *any* name exported by any module in scope, just as if there
         -- was an "import qualified M" declaration for every module.
         allow_qual <- doptM Opt_ImplicitImportQualified
         --  *any* name exported by any module in scope, just as if there
         -- was an "import qualified M" declaration for every module.
         allow_qual <- doptM Opt_ImplicitImportQualified
-       ; mod <- getModule
+       ; is_ghci <- getIsGHCi
                -- This test is not expensive,
                -- and only happens for failed lookups
                -- This test is not expensive,
                -- and only happens for failed lookups
-       ; if isQual rdr_name && allow_qual && mod == iNTERACTIVE
+       ; if isQual rdr_name && allow_qual && is_ghci
          then lookupQualifiedName rdr_name
          then lookupQualifiedName rdr_name
-         else unboundName rdr_name } } }
+         else unboundName WL_Any rdr_name } } } } }
+
+
+lookupGlobalOccRn :: RdrName -> RnM Name
+-- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
+-- environment.  Adds an error message if the RdrName is not in scope.
+lookupGlobalOccRn rdr_name
+  = do { mb_name <- lookupGlobalOccRn_maybe rdr_name
+       ; case mb_name of
+           Just n  -> return n
+           Nothing -> unboundName WL_Global rdr_name }
 
 lookupGlobalOccRn_maybe :: RdrName -> RnM (Maybe Name)
 -- No filter function; does not report an error on failure
 
 lookupGlobalOccRn_maybe :: RdrName -> RnM (Maybe Name)
 -- No filter function; does not report an error on failure
@@ -385,15 +406,6 @@ lookupGlobalOccRn_maybe rdr_name
                Just gre -> return (Just (gre_name gre)) }
 
 
                Just gre -> return (Just (gre_name gre)) }
 
 
-unboundName :: RdrName -> RnM Name
-unboundName rdr_name 
-  = do { addErr (unknownNameErr rdr_name)
-       ; env <- getGlobalRdrEnv;
-       ; traceRn (vcat [unknownNameErr rdr_name, 
-                        ptext (sLit "Global envt is:"),
-                        nest 3 (pprGlobalRdrEnv env)])
-       ; return (mkUnboundName rdr_name) }
-
 --------------------------------------------------
 --     Lookup in the Global RdrEnv of the module
 --------------------------------------------------
 --------------------------------------------------
 --     Lookup in the Global RdrEnv of the module
 --------------------------------------------------
@@ -411,7 +423,7 @@ lookupGreRn rdr_name
            Just gre -> return gre ;
            Nothing  -> do
        { traceRn $ text "lookupGreRn"
            Just gre -> return gre ;
            Nothing  -> do
        { traceRn $ text "lookupGreRn"
-       ; name <- unboundName rdr_name
+        ; name <- unboundName WL_Global rdr_name
        ; return (GRE { gre_name = name, gre_par = NoParent,
                        gre_prov = LocalDef }) }}}
 
        ; return (GRE { gre_name = name, gre_par = NoParent,
                        gre_prov = LocalDef }) }}}
 
@@ -473,7 +485,7 @@ lookupQualifiedName rdr_name
           name == occ ] of
       ((mod,occ):ns) -> ASSERT (null ns) 
                        lookupOrig mod occ
           name == occ ] of
       ((mod,occ):ns) -> ASSERT (null ns) 
                        lookupOrig mod occ
-      _ -> unboundName rdr_name
+      _ -> unboundName WL_Any rdr_name
 
   | otherwise
   = pprPanic "RnEnv.lookupQualifiedName" (ppr rdr_name)
 
   | otherwise
   = pprPanic "RnEnv.lookupQualifiedName" (ppr rdr_name)
@@ -481,6 +493,8 @@ lookupQualifiedName rdr_name
     doc = ptext (sLit "Need to find") <+> ppr rdr_name
 \end{code}
 
     doc = ptext (sLit "Need to find") <+> ppr rdr_name
 \end{code}
 
+Note [Looking up signature names]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 lookupSigOccRn is used for type signatures and pragmas
 Is this valid?
   module A
 lookupSigOccRn is used for type signatures and pragmas
 Is this valid?
   module A
@@ -501,10 +515,13 @@ return the imported 'f', so that later on the reanamer will
 correctly report "misplaced type sig".
 
 \begin{code}
 correctly report "misplaced type sig".
 
 \begin{code}
-lookupSigOccRn :: Maybe NameSet           -- Just ns => source file; these are the binders
+lookupSigOccRn :: Maybe NameSet           -- Just ns => these are the binders
                                   --            in the same group
                                   --            in the same group
-                                  -- Nothing => hs-boot file; signatures without 
+                                  -- Nothing => signatures without 
                                   --            binders are expected
                                   --            binders are expected
+                                  --            (a) top-level (SPECIALISE prags)
+                                  --            (b) class decls
+                                  --            (c) hs-boot files
               -> Sig RdrName
               -> Located RdrName -> RnM (Located Name)
 lookupSigOccRn mb_bound_names sig
               -> Sig RdrName
               -> Located RdrName -> RnM (Located Name)
 lookupSigOccRn mb_bound_names sig
@@ -514,29 +531,29 @@ lookupSigOccRn mb_bound_names sig
           Left err   -> do { addErr err; return (mkUnboundName rdr_name) }
           Right name -> return name }
 
           Left err   -> do { addErr err; return (mkUnboundName rdr_name) }
           Right name -> return name }
 
-lookupBindGroupOcc :: Maybe NameSet  -- Just ns => source file; these are the binders
-                                    --                  in the same group
-                                    -- Nothing => hs-boot file; signatures without 
-                                    --                  binders are expected
-                  -> SDoc
+lookupBindGroupOcc :: Maybe NameSet  -- See notes on the (Maybe NameSet)
+                  -> SDoc           --  in lookupSigOccRn
                   -> RdrName -> RnM (Either Message Name)
 -- Looks up the RdrName, expecting it to resolve to one of the 
 -- bound names passed in.  If not, return an appropriate error message
                   -> RdrName -> RnM (Either Message Name)
 -- Looks up the RdrName, expecting it to resolve to one of the 
 -- bound names passed in.  If not, return an appropriate error message
+--
+-- See Note [Looking up signature names]
 lookupBindGroupOcc mb_bound_names what rdr_name
 lookupBindGroupOcc mb_bound_names what rdr_name
-  = do { local_env <- getLocalRdrEnv
-       ; case lookupLocalRdrEnv local_env rdr_name of 
-           Just n  -> check_local_name n
-           Nothing -> do       -- Not defined in a nested scope
+  = do  { local_env <- getLocalRdrEnv
+        ; case lookupLocalRdrEnv local_env rdr_name of {
+            Just n  -> check_local_name n;
+            Nothing -> do       -- Not defined in a nested scope
 
         { env <- getGlobalRdrEnv 
 
         { env <- getGlobalRdrEnv 
-       ; let gres = lookupGlobalRdrEnv env (rdrNameOcc rdr_name)
-       ; case (filter isLocalGRE gres) of
-           (gre:_) -> check_local_name (gre_name gre)
-                       -- If there is more than one local GRE for the 
-                       -- same OccName, that will be reported separately
-           [] | null gres -> bale_out_with empty
-              | otherwise -> bale_out_with import_msg
-       }}
+        ; let gres = lookupGlobalRdrEnv env (rdrNameOcc rdr_name)
+        ; case (filter isLocalGRE gres) of
+            (gre:_) -> check_local_name (gre_name gre)
+                        -- If there is more than one local GRE for the 
+                        -- same OccName 'f', that will be reported separately
+                        -- as a duplicate top-level binding for 'f'
+            [] | null gres -> bale_out_with empty
+               | otherwise -> bale_out_with import_msg
+        }}}
     where
       check_local_name name    -- The name is in scope, and not imported
          = case mb_bound_names of
     where
       check_local_name name    -- The name is in scope, and not imported
          = case mb_bound_names of
@@ -629,23 +646,17 @@ type MiniFixityEnv = FastStringEnv (Located Fixity)
 --------------------------------
 -- Used for nested fixity decls to bind names along with their fixities.
 -- the fixities are given as a UFM from an OccName's FastString to a fixity decl
 --------------------------------
 -- Used for nested fixity decls to bind names along with their fixities.
 -- the fixities are given as a UFM from an OccName's FastString to a fixity decl
--- Also check for unused binders
-bindLocalNamesFV_WithFixities :: [Name]
-                             -> MiniFixityEnv
-                             -> RnM (a, FreeVars) -> RnM (a, FreeVars)
-bindLocalNamesFV_WithFixities names fixities thing_inside
-  = bindLocalNamesFV names $
-    extendFixityEnv boundFixities $ 
-    thing_inside
+
+addLocalFixities :: MiniFixityEnv -> [Name] -> RnM a -> RnM a
+addLocalFixities mini_fix_env names thing_inside
+  = extendFixityEnv (mapCatMaybes find_fixity names) thing_inside
   where
   where
-    -- find the names that have fixity decls
-    boundFixities = foldr 
-                        (\ name -> \ acc -> 
-                         -- check whether this name has a fixity decl
-                          case lookupFsEnv fixities (occNameFS (nameOccName name)) of
-                               Just (L _ fix) -> (name, FixItem (nameOccName name) fix) : acc
-                               Nothing -> acc) [] names
-    -- bind the names; extend the fixity env; do the thing inside
+    find_fixity name 
+      = case lookupFsEnv mini_fix_env (occNameFS occ) of
+          Just (L _ fix) -> Just (name, FixItem occ fix)
+          Nothing        -> Nothing
+      where
+        occ = nameOccName name
 \end{code}
 
 --------------------------------
 \end{code}
 
 --------------------------------
@@ -707,7 +718,7 @@ lookupTyFixityRn (L _ n) = lookupFixityRn n
 %*                                                                     *
                        Rebindable names
        Dealing with rebindable syntax is driven by the 
 %*                                                                     *
                        Rebindable names
        Dealing with rebindable syntax is driven by the 
-       Opt_NoImplicitPrelude dynamic flag.
+       Opt_RebindableSyntax dynamic flag.
 
        In "deriving" code we don't want to use rebindable syntax
        so we switch off the flag locally
 
        In "deriving" code we don't want to use rebindable syntax
        so we switch off the flag locally
@@ -743,11 +754,22 @@ We treat the orignal (standard) names as free-vars too, because the type checker
 checks the type of the user thing against the type of the standard thing.
 
 \begin{code}
 checks the type of the user thing against the type of the standard thing.
 
 \begin{code}
+lookupIfThenElse :: RnM (Maybe (SyntaxExpr Name), FreeVars)
+-- Different to lookupSyntaxName because in the non-rebindable
+-- case we desugar directly rather than calling an existing function
+-- Hence the (Maybe (SyntaxExpr Name)) return type
+lookupIfThenElse 
+  = do { rebind <- xoptM Opt_RebindableSyntax
+       ; if not rebind 
+         then return (Nothing, emptyFVs)
+         else do { ite <- lookupOccRn (mkVarUnqual (fsLit "ifThenElse"))
+                 ; return (Just (HsVar ite), unitFV ite) } }
+
 lookupSyntaxName :: Name                               -- The standard name
                 -> RnM (SyntaxExpr Name, FreeVars)     -- Possibly a non-standard name
 lookupSyntaxName std_name
 lookupSyntaxName :: Name                               -- The standard name
                 -> RnM (SyntaxExpr Name, FreeVars)     -- Possibly a non-standard name
 lookupSyntaxName std_name
-  = doptM Opt_ImplicitPrelude          `thenM` \ implicit_prelude -> 
-    if implicit_prelude then normal_case
+  = xoptM Opt_RebindableSyntax         `thenM` \ rebindable_on -> 
+    if not rebindable_on then normal_case 
     else
        -- Get the similarly named thing from the local environment
     lookupOccRn (mkRdrUnqual (nameOccName std_name)) `thenM` \ usr_name ->
     else
        -- Get the similarly named thing from the local environment
     lookupOccRn (mkRdrUnqual (nameOccName std_name)) `thenM` \ usr_name ->
@@ -758,8 +780,8 @@ lookupSyntaxName std_name
 lookupSyntaxTable :: [Name]                            -- Standard names
                  -> RnM (SyntaxTable Name, FreeVars)   -- See comments with HsExpr.ReboundNames
 lookupSyntaxTable std_names
 lookupSyntaxTable :: [Name]                            -- Standard names
                  -> RnM (SyntaxTable Name, FreeVars)   -- See comments with HsExpr.ReboundNames
 lookupSyntaxTable std_names
-  = doptM Opt_ImplicitPrelude          `thenM` \ implicit_prelude -> 
-    if implicit_prelude then normal_case 
+  = xoptM Opt_RebindableSyntax         `thenM` \ rebindable_on -> 
+    if not rebindable_on then normal_case 
     else
        -- Get the similarly named thing from the local environment
     mapM (lookupOccRn . mkRdrUnqual . nameOccName) std_names   `thenM` \ usr_names ->
     else
        -- Get the similarly named thing from the local environment
     mapM (lookupOccRn . mkRdrUnqual . nameOccName) std_names   `thenM` \ usr_names ->
@@ -795,20 +817,11 @@ newLocalBndrsRn :: [Located RdrName] -> RnM [Name]
 newLocalBndrsRn = mapM newLocalBndrRn
 
 ---------------------
 newLocalBndrsRn = mapM newLocalBndrRn
 
 ---------------------
-checkDupAndShadowedRdrNames :: SDoc -> [Located RdrName] -> RnM ()
-checkDupAndShadowedRdrNames doc loc_rdr_names
-  = do { checkDupRdrNames doc loc_rdr_names
-       ; envs <- getRdrEnvs
-       ; checkShadowedNames doc envs 
-               [(loc,rdrNameOcc rdr) | L loc rdr <- loc_rdr_names] }
-
----------------------
-bindLocatedLocalsRn :: SDoc    -- Documentation string for error message
-                   -> [Located RdrName]
+bindLocatedLocalsRn :: [Located RdrName]
                    -> ([Name] -> RnM a)
                    -> RnM a
                    -> ([Name] -> RnM a)
                    -> RnM a
-bindLocatedLocalsRn doc_str rdr_names_w_loc enclosed_scope
-  = do { checkDupAndShadowedRdrNames doc_str rdr_names_w_loc
+bindLocatedLocalsRn rdr_names_w_loc enclosed_scope
+  = do { checkDupAndShadowedRdrNames rdr_names_w_loc
 
        -- Make fresh Names and extend the environment
        ; names <- newLocalBndrsRn rdr_names_w_loc
 
        -- Make fresh Names and extend the environment
        ; names <- newLocalBndrsRn rdr_names_w_loc
@@ -829,27 +842,35 @@ bindLocalName name enclosed_scope
 bindLocalNamesFV :: [Name] -> RnM (a, FreeVars) -> RnM (a, FreeVars)
 bindLocalNamesFV names enclosed_scope
   = do { (result, fvs) <- bindLocalNames names enclosed_scope
 bindLocalNamesFV :: [Name] -> RnM (a, FreeVars) -> RnM (a, FreeVars)
 bindLocalNamesFV names enclosed_scope
   = do { (result, fvs) <- bindLocalNames names enclosed_scope
-       ; return (result, delListFromNameSet fvs names) }
+       ; return (result, delFVs names fvs) }
 
 
 -------------------------------------
        -- binLocalsFVRn is the same as bindLocalsRn
        -- except that it deals with free vars
 
 
 -------------------------------------
        -- binLocalsFVRn is the same as bindLocalsRn
        -- except that it deals with free vars
-bindLocatedLocalsFV :: SDoc -> [Located RdrName] 
+bindLocatedLocalsFV :: [Located RdrName] 
                     -> ([Name] -> RnM (a,FreeVars)) -> RnM (a, FreeVars)
                     -> ([Name] -> RnM (a,FreeVars)) -> RnM (a, FreeVars)
-bindLocatedLocalsFV doc rdr_names enclosed_scope
-  = bindLocatedLocalsRn doc rdr_names  $ \ names ->
+bindLocatedLocalsFV rdr_names enclosed_scope
+  = bindLocatedLocalsRn rdr_names      $ \ names ->
     enclosed_scope names               `thenM` \ (thing, fvs) ->
     enclosed_scope names               `thenM` \ (thing, fvs) ->
-    return (thing, delListFromNameSet fvs names)
+    return (thing, delFVs names fvs)
 
 -------------------------------------
 
 -------------------------------------
-bindTyVarsRn :: SDoc -> [LHsTyVarBndr RdrName]
+bindTyVarsFV ::  [LHsTyVarBndr RdrName]
+             -> ([LHsTyVarBndr Name] -> RnM (a, FreeVars))
+             -> RnM (a, FreeVars)
+bindTyVarsFV tyvars thing_inside
+  = bindTyVarsRn tyvars $ \ tyvars' ->
+    do { (res, fvs) <- thing_inside tyvars'
+       ; return (res, delFVs (map hsLTyVarName tyvars') fvs) }
+
+bindTyVarsRn ::  [LHsTyVarBndr RdrName]
              -> ([LHsTyVarBndr Name] -> RnM a)
              -> RnM a
 -- Haskell-98 binding of type variables; e.g. within a data type decl
              -> ([LHsTyVarBndr Name] -> RnM a)
              -> RnM a
 -- Haskell-98 binding of type variables; e.g. within a data type decl
-bindTyVarsRn doc_str tyvar_names enclosed_scope
-  = bindLocatedLocalsRn doc_str located_tyvars $ \ names ->
-    do { kind_sigs_ok <- doptM Opt_KindSignatures
+bindTyVarsRn tyvar_names enclosed_scope
+  = bindLocatedLocalsRn located_tyvars $ \ names ->
+    do { kind_sigs_ok <- xoptM Opt_KindSignatures
        ; unless (null kinded_tyvars || kind_sigs_ok) 
                        (mapM_ (addErr . kindSigErr) kinded_tyvars)
        ; enclosed_scope (zipWith replace tyvar_names names) }
        ; unless (null kinded_tyvars || kind_sigs_ok) 
                        (mapM_ (addErr . kindSigErr) kinded_tyvars)
        ; enclosed_scope (zipWith replace tyvar_names names) }
@@ -862,7 +883,7 @@ bindPatSigTyVars :: [LHsType RdrName] -> ([Name] -> RnM a) -> RnM a
   -- Find the type variables in the pattern type 
   -- signatures that must be brought into scope
 bindPatSigTyVars tys thing_inside
   -- Find the type variables in the pattern type 
   -- signatures that must be brought into scope
 bindPatSigTyVars tys thing_inside
-  = do         { scoped_tyvars <- doptM Opt_ScopedTypeVariables
+  = do         { scoped_tyvars <- xoptM Opt_ScopedTypeVariables
        ; if not scoped_tyvars then 
                thing_inside []
          else 
        ; if not scoped_tyvars then 
                thing_inside []
          else 
@@ -875,9 +896,7 @@ bindPatSigTyVars tys thing_inside
                --      f (x :: t) (y :: t) = ....
                -- We don't want to complain about binding t twice!
 
                --      f (x :: t) (y :: t) = ....
                -- We don't want to complain about binding t twice!
 
-       ; bindLocatedLocalsRn doc_sig nubbed_tvs thing_inside }}
-  where
-    doc_sig = text "In a pattern type-signature"
+       ; bindLocatedLocalsRn nubbed_tvs thing_inside }}
 
 bindPatSigTyVarsFV :: [LHsType RdrName]
                   -> RnM (a, FreeVars)
 
 bindPatSigTyVarsFV :: [LHsType RdrName]
                   -> RnM (a, FreeVars)
@@ -891,7 +910,7 @@ bindSigTyVarsFV :: [Name]
                -> RnM (a, FreeVars)
                -> RnM (a, FreeVars)
 bindSigTyVarsFV tvs thing_inside
                -> RnM (a, FreeVars)
                -> RnM (a, FreeVars)
 bindSigTyVarsFV tvs thing_inside
-  = do { scoped_tyvars <- doptM Opt_ScopedTypeVariables
+  = do { scoped_tyvars <- xoptM Opt_ScopedTypeVariables
        ; if not scoped_tyvars then 
                thing_inside 
          else
        ; if not scoped_tyvars then 
                thing_inside 
          else
@@ -902,30 +921,42 @@ extendTyVarEnvFVRn :: [Name] -> RnM (a, FreeVars) -> RnM (a, FreeVars)
 extendTyVarEnvFVRn tyvars thing_inside = bindLocalNamesFV tyvars thing_inside
 
 -------------------------------------
 extendTyVarEnvFVRn tyvars thing_inside = bindLocalNamesFV tyvars thing_inside
 
 -------------------------------------
-checkDupRdrNames :: SDoc
-                -> [Located RdrName]
-                -> RnM ()
-checkDupRdrNames doc_str rdr_names_w_loc
+checkDupRdrNames :: [Located RdrName] -> RnM ()
+checkDupRdrNames rdr_names_w_loc
   =    -- Check for duplicated names in a binding group
   =    -- Check for duplicated names in a binding group
-    mapM_ (dupNamesErr getLoc doc_str) dups
+    mapM_ (dupNamesErr getLoc) dups
   where
     (_, dups) = removeDups (\n1 n2 -> unLoc n1 `compare` unLoc n2) rdr_names_w_loc
 
   where
     (_, dups) = removeDups (\n1 n2 -> unLoc n1 `compare` unLoc n2) rdr_names_w_loc
 
-checkDupNames :: SDoc
-             -> [Name]
-             -> RnM ()
-checkDupNames doc_str names
+checkDupNames :: [Name] -> RnM ()
+checkDupNames names
   =    -- Check for duplicated names in a binding group
   =    -- Check for duplicated names in a binding group
-    mapM_ (dupNamesErr nameSrcSpan doc_str) dups
+    mapM_ (dupNamesErr nameSrcSpan) dups
   where
     (_, dups) = removeDups (\n1 n2 -> nameOccName n1 `compare` nameOccName n2) names
 
   where
     (_, dups) = removeDups (\n1 n2 -> nameOccName n1 `compare` nameOccName n2) names
 
+---------------------
+checkDupAndShadowedRdrNames :: [Located RdrName] -> RnM ()
+checkDupAndShadowedRdrNames loc_rdr_names
+  = do { checkDupRdrNames loc_rdr_names
+       ; envs <- getRdrEnvs
+       ; checkShadowedOccs envs loc_occs }
+  where
+    loc_occs = [(loc,rdrNameOcc rdr) | L loc rdr <- loc_rdr_names]
+
+checkDupAndShadowedNames :: (GlobalRdrEnv, LocalRdrEnv) -> [Name] -> RnM ()
+checkDupAndShadowedNames envs names
+  = do { checkDupNames names
+       ; checkShadowedOccs envs loc_occs }
+  where
+    loc_occs = [(nameSrcSpan name, nameOccName name) | name <- names]
+
 -------------------------------------
 -------------------------------------
-checkShadowedNames :: SDoc -> (GlobalRdrEnv, LocalRdrEnv) -> [(SrcSpan,OccName)] -> RnM ()
-checkShadowedNames doc_str (global_env,local_env) loc_rdr_names
-  = ifOptM Opt_WarnNameShadowing $ 
-    do { traceRn (text "shadow" <+> ppr loc_rdr_names)
-       ; mapM_ check_shadow loc_rdr_names }
+checkShadowedOccs :: (GlobalRdrEnv, LocalRdrEnv) -> [(SrcSpan,OccName)] -> RnM ()
+checkShadowedOccs (global_env,local_env) loc_occs
+  = ifDOptM Opt_WarnNameShadowing $ 
+    do { traceRn (text "shadow" <+> ppr loc_occs)
+       ; mapM_ check_shadow loc_occs }
   where
     check_shadow (loc, occ)
         | startsWithUnderscore occ = return () -- Do not report shadowing for "_x"
   where
     check_shadow (loc, occ)
         | startsWithUnderscore occ = return () -- Do not report shadowing for "_x"
@@ -935,7 +966,7 @@ checkShadowedNames doc_str (global_env,local_env) loc_rdr_names
                         ; complain (map pprNameProvenance gres') }
        where
          complain []      = return ()
                         ; complain (map pprNameProvenance gres') }
        where
          complain []      = return ()
-         complain pp_locs = addWarnAt loc (shadowedNameWarn doc_str occ pp_locs)
+         complain pp_locs = addWarnAt loc (shadowedNameWarn occ pp_locs)
          mb_local = lookupLocalRdrOcc local_env occ
           gres     = lookupGRE_RdrName (mkRdrUnqual occ) global_env
                -- Make an Unqualified RdrName and look that up, so that
          mb_local = lookupLocalRdrOcc local_env occ
           gres     = lookupGRE_RdrName (mkRdrUnqual occ) global_env
                -- Make an Unqualified RdrName and look that up, so that
@@ -946,7 +977,7 @@ checkShadowedNames doc_str (global_env,local_env) loc_rdr_names
        -- punning or wild-cards are on (cf Trac #2723)
     is_shadowed_gre gre@(GRE { gre_par = ParentIs _ })
        = do { dflags <- getDOpts
        -- punning or wild-cards are on (cf Trac #2723)
     is_shadowed_gre gre@(GRE { gre_par = ParentIs _ })
        = do { dflags <- getDOpts
-            ; if (dopt Opt_RecordPuns dflags || dopt Opt_RecordWildCards dflags) 
+            ; if (xopt Opt_RecordPuns dflags || xopt Opt_RecordWildCards dflags) 
               then do { is_fld <- is_rec_fld gre; return (not is_fld) }
               else return True }
     is_shadowed_gre _other = return True
               then do { is_fld <- is_rec_fld gre; return (not is_fld) }
               else return True }
     is_shadowed_gre _other = return True
@@ -961,17 +992,180 @@ checkShadowedNames doc_str (global_env,local_env) loc_rdr_names
 
 %************************************************************************
 %*                                                                     *
 
 %************************************************************************
 %*                                                                     *
+               What to do when a lookup fails
+%*                                                                      *
+%************************************************************************
+
+\begin{code}
+data WhereLooking = WL_Any        -- Any binding
+                  | WL_Global     -- Any top-level binding (local or imported)
+                  | WL_LocalTop   -- Any top-level binding in this module
+
+unboundName :: WhereLooking -> RdrName -> RnM Name
+unboundName where_look rdr_name
+  = do  { show_helpful_errors <- doptM Opt_HelpfulErrors
+        ; let err = unknownNameErr rdr_name
+        ; if not show_helpful_errors
+          then addErr err
+          else do { extra_err <- unknownNameSuggestErr where_look rdr_name
+                  ; addErr (err $$ extra_err) }
+
+        ; env <- getGlobalRdrEnv;
+       ; traceRn (vcat [unknownNameErr rdr_name, 
+                        ptext (sLit "Global envt is:"),
+                        nest 3 (pprGlobalRdrEnv env)])
+
+        ; return (mkUnboundName rdr_name) }
+
+unknownNameErr :: RdrName -> SDoc
+unknownNameErr rdr_name
+  = vcat [ hang (ptext (sLit "Not in scope:")) 
+             2 (pprNonVarNameSpace (occNameSpace (rdrNameOcc rdr_name))
+                         <+> quotes (ppr rdr_name))
+        , extra ]
+  where
+    extra | rdr_name == forall_tv_RDR = perhapsForallMsg
+         | otherwise                 = empty
+
+type HowInScope = Either SrcSpan ImpDeclSpec
+     -- Left loc    =>  locally bound at loc
+     -- Right ispec =>  imported as specified by ispec
+
+unknownNameSuggestErr :: WhereLooking -> RdrName -> RnM SDoc
+unknownNameSuggestErr where_look tried_rdr_name
+  = do { local_env <- getLocalRdrEnv
+       ; global_env <- getGlobalRdrEnv
+
+       ; let all_possibilities :: [(String, (RdrName, HowInScope))]
+             all_possibilities
+                =  [ (showSDoc (ppr r), (r, Left loc))
+                   | (r,loc) <- local_possibilities local_env ]
+                ++ [ (showSDoc (ppr r), rp) | (r,rp) <- global_possibilities global_env ]
+
+             suggest = fuzzyLookup (showSDoc (ppr tried_rdr_name)) all_possibilities
+             perhaps = ptext (sLit "Perhaps you meant")
+             extra_err = case suggest of
+                           []  -> empty
+                           [p] -> perhaps <+> pp_item p
+                           ps  -> sep [ perhaps <+> ptext (sLit "one of these:")
+                                      , nest 2 (pprWithCommas pp_item ps) ]
+       ; return extra_err }
+  where
+    pp_item :: (RdrName, HowInScope) -> SDoc
+    pp_item (rdr, Left loc) = quotes (ppr rdr) <+>   -- Locally defined
+                              parens (ptext (sLit "line") <+> int (srcSpanStartLine loc'))
+        where loc' = case loc of
+                     UnhelpfulSpan _ ->
+                         panic "unknownNameSuggestErr UnhelpfulSpan"
+                     RealSrcSpan l -> l
+    pp_item (rdr, Right is) = quotes (ppr rdr) <+>   -- Imported
+                              parens (ptext (sLit "imported from") <+> ppr (is_mod is))
+
+    tried_occ     = rdrNameOcc tried_rdr_name
+    tried_is_sym  = isSymOcc tried_occ
+    tried_ns      = occNameSpace tried_occ
+    tried_is_qual = isQual tried_rdr_name
+
+    correct_name_space occ =  occNameSpace occ == tried_ns
+                           && isSymOcc occ == tried_is_sym
+        -- Treat operator and non-operators as non-matching
+        -- This heuristic avoids things like
+        --      Not in scope 'f'; perhaps you meant '+' (from Prelude)
+
+    local_ok = case where_look of { WL_Any -> True; _ -> False }
+    local_possibilities :: LocalRdrEnv -> [(RdrName, SrcSpan)]
+    local_possibilities env
+      | tried_is_qual = []
+      | not local_ok  = []
+      | otherwise     = [ (mkRdrUnqual occ, nameSrcSpan name)
+                       | name <- occEnvElts env
+                       , let occ = nameOccName name
+                       , correct_name_space occ]
+
+    gre_ok :: GlobalRdrElt -> Bool
+    gre_ok = case where_look of
+                   WL_LocalTop -> isLocalGRE
+                   _           -> \_ -> True
+
+    global_possibilities :: GlobalRdrEnv -> [(RdrName, (RdrName, HowInScope))]
+    global_possibilities global_env
+      | tried_is_qual = [ (rdr_qual, (rdr_qual, how))
+                        | gre <- globalRdrEnvElts global_env
+                        , gre_ok gre
+                        , let name = gre_name gre
+                             occ  = nameOccName name
+                        , correct_name_space occ
+                        , (mod, how) <- quals_in_scope name (gre_prov gre)
+                        , let rdr_qual = mkRdrQual mod occ ]
+
+      | otherwise = [ (rdr_unqual, pair)
+                    | gre <- globalRdrEnvElts global_env
+                    , gre_ok gre
+                    , let name = gre_name gre
+                          prov = gre_prov gre
+                          occ  = nameOccName name
+                          rdr_unqual = mkRdrUnqual occ
+                    , correct_name_space occ
+                    , pair <- case (unquals_in_scope name prov, quals_only occ prov) of
+                                (how:_, _)    -> [ (rdr_unqual, how) ]
+                                ([],    pr:_) -> [ pr ]  -- See Note [Only-quals]
+                                ([],    [])   -> [] ]
+
+              -- Note [Only-quals]
+              -- The second alternative returns those names with the same
+              -- OccName as the one we tried, but live in *qualified* imports
+                     -- e.g. if you have:
+                     --
+                     -- > import qualified Data.Map as Map
+                     -- > foo :: Map
+                     --
+                     -- then we suggest @Map.Map@.
+
+    --------------------
+    unquals_in_scope :: Name -> Provenance -> [HowInScope]
+    unquals_in_scope n LocalDef      = [ Left (nameSrcSpan n) ]
+    unquals_in_scope _ (Imported is) = [ Right ispec
+                                       | i <- is, let ispec = is_decl i
+                                       , not (is_qual ispec) ]
+
+    --------------------
+    quals_in_scope :: Name -> Provenance -> [(ModuleName, HowInScope)]
+    -- Ones for which the qualified version is in scope
+    quals_in_scope n LocalDef      = case nameModule_maybe n of
+                                       Nothing -> []
+                                       Just m  -> [(moduleName m, Left (nameSrcSpan n))]
+    quals_in_scope _ (Imported is) = [ (is_as ispec, Right ispec)
+                                     | i <- is, let ispec = is_decl i ]
+
+    --------------------
+    quals_only :: OccName -> Provenance -> [(RdrName, HowInScope)]
+    -- Ones for which *only* the qualified version is in scope
+    quals_only _   LocalDef      = []
+    quals_only occ (Imported is) = [ (mkRdrQual (is_as ispec) occ, Right ispec)
+                                   | i <- is, let ispec = is_decl i, is_qual ispec ]
+\end{code}
+
+%************************************************************************
+%*                                                                     *
 \subsection{Free variable manipulation}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
 -- A useful utility
 \subsection{Free variable manipulation}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
 -- A useful utility
+addFvRn :: FreeVars -> RnM (thing, FreeVars) -> RnM (thing, FreeVars)
+addFvRn fvs1 thing_inside = do { (res, fvs2) <- thing_inside
+                               ; return (res, fvs1 `plusFV` fvs2) }
+
 mapFvRn :: (a -> RnM (b, FreeVars)) -> [a] -> RnM ([b], FreeVars)
 mapFvRn f xs = do stuff <- mapM f xs
                   case unzip stuff of
                       (ys, fvs_s) -> return (ys, plusFVs fvs_s)
 
 mapFvRn :: (a -> RnM (b, FreeVars)) -> [a] -> RnM ([b], FreeVars)
 mapFvRn f xs = do stuff <- mapM f xs
                   case unzip stuff of
                       (ys, fvs_s) -> return (ys, plusFVs fvs_s)
 
+mapMaybeFvRn :: (a -> RnM (b, FreeVars)) -> Maybe a -> RnM (Maybe b, FreeVars)
+mapMaybeFvRn _ Nothing = return (Nothing, emptyFVs)
+mapMaybeFvRn f (Just x) = do { (y, fvs) <- f x; return (Just y, fvs) }
+
 -- because some of the rename functions are CPSed:
 -- maps the function across the list from left to right; 
 -- collects all the free vars into one set
 -- because some of the rename functions are CPSed:
 -- maps the function across the list from left to right; 
 -- collects all the free vars into one set
@@ -992,22 +1186,19 @@ mapFvRnCPS f (x:xs) cont = f x              $ \ x' ->
 %************************************************************************
 
 \begin{code}
 %************************************************************************
 
 \begin{code}
-warnUnusedModules :: [(ModuleName,SrcSpan)] -> RnM ()
-warnUnusedModules mods
-  = ifOptM Opt_WarnUnusedImports (mapM_ bleat mods)
-  where
-    bleat (mod,loc) = addWarnAt loc (mk_warn mod)
-    mk_warn m = vcat [ptext (sLit "Module") <+> quotes (ppr m)
-                       <+> text "is imported, but nothing from it is used,",
-                     nest 2 (ptext (sLit "except perhaps instances visible in") 
-                       <+> quotes (ppr m)),
-                     ptext (sLit "To suppress this warning, use:") 
-                       <+> ptext (sLit "import") <+> ppr m <> parens empty ]
-
-
-warnUnusedImports, warnUnusedTopBinds :: [GlobalRdrElt] -> RnM ()
-warnUnusedImports gres  = ifOptM Opt_WarnUnusedImports (warnUnusedGREs gres)
-warnUnusedTopBinds gres = ifOptM Opt_WarnUnusedBinds   (warnUnusedGREs gres)
+warnUnusedTopBinds :: [GlobalRdrElt] -> RnM ()
+warnUnusedTopBinds gres
+    = ifDOptM Opt_WarnUnusedBinds
+    $ do isBoot <- tcIsHsBoot
+         let noParent gre = case gre_par gre of
+                            NoParent -> True
+                            ParentIs _ -> False
+             -- Don't warn about unused bindings with parents in
+             -- .hs-boot files, as you are sometimes required to give
+             -- unused bindings (trac #3449).
+             gres' = if isBoot then filter noParent gres
+                               else                 gres
+         warnUnusedGREs gres'
 
 warnUnusedLocalBinds, warnUnusedMatches :: [Name] -> FreeVars -> RnM ()
 warnUnusedLocalBinds = check_unused Opt_WarnUnusedBinds
 
 warnUnusedLocalBinds, warnUnusedMatches :: [Name] -> FreeVars -> RnM ()
 warnUnusedLocalBinds = check_unused Opt_WarnUnusedBinds
@@ -1015,7 +1206,7 @@ warnUnusedMatches    = check_unused Opt_WarnUnusedMatches
 
 check_unused :: DynFlag -> [Name] -> FreeVars -> RnM ()
 check_unused flag bound_names used_names
 
 check_unused :: DynFlag -> [Name] -> FreeVars -> RnM ()
 check_unused flag bound_names used_names
- = ifOptM flag (warnUnusedLocals (filterOut (`elemNameSet` used_names) bound_names))
+ = ifDOptM flag (warnUnusedLocals (filterOut (`elemNameSet` used_names) bound_names))
 
 -------------------------
 --     Helpers
 
 -------------------------
 --     Helpers
@@ -1068,24 +1259,13 @@ addNameClashErrRn rdr_name names
     (np1:nps) = names
     msg1 = ptext  (sLit "either") <+> mk_ref np1
     msgs = [ptext (sLit "    or") <+> mk_ref np | np <- nps]
     (np1:nps) = names
     msg1 = ptext  (sLit "either") <+> mk_ref np1
     msgs = [ptext (sLit "    or") <+> mk_ref np | np <- nps]
-    mk_ref gre = quotes (ppr (gre_name gre)) <> comma <+> pprNameProvenance gre
+    mk_ref gre = sep [quotes (ppr (gre_name gre)) <> comma, pprNameProvenance gre]
 
 
-shadowedNameWarn :: SDoc -> OccName -> [SDoc] -> SDoc
-shadowedNameWarn doc occ shadowed_locs
+shadowedNameWarn :: OccName -> [SDoc] -> SDoc
+shadowedNameWarn occ shadowed_locs
   = sep [ptext (sLit "This binding for") <+> quotes (ppr occ)
            <+> ptext (sLit "shadows the existing binding") <> plural shadowed_locs,
         nest 2 (vcat shadowed_locs)]
   = sep [ptext (sLit "This binding for") <+> quotes (ppr occ)
            <+> ptext (sLit "shadows the existing binding") <> plural shadowed_locs,
         nest 2 (vcat shadowed_locs)]
-    $$ doc
-
-unknownNameErr :: RdrName -> SDoc
-unknownNameErr rdr_name
-  = vcat [ hang (ptext (sLit "Not in scope:")) 
-             2 (pprNonVarNameSpace (occNameSpace (rdrNameOcc rdr_name))
-                         <+> quotes (ppr rdr_name))
-        , extra ]
-  where
-    extra | rdr_name == forall_tv_RDR = perhapsForallMsg
-         | otherwise                 = empty
 
 perhapsForallMsg :: SDoc
 perhapsForallMsg 
 
 perhapsForallMsg :: SDoc
 perhapsForallMsg 
@@ -1102,18 +1282,15 @@ badOrigBinding name
   = ptext (sLit "Illegal binding of built-in syntax:") <+> ppr (rdrNameOcc name)
        -- The rdrNameOcc is because we don't want to print Prelude.(,)
 
   = ptext (sLit "Illegal binding of built-in syntax:") <+> ppr (rdrNameOcc name)
        -- The rdrNameOcc is because we don't want to print Prelude.(,)
 
-dupNamesErr :: Outputable n => (n -> SrcSpan) -> SDoc -> [n] -> RnM ()
-dupNamesErr get_loc descriptor names
+dupNamesErr :: Outputable n => (n -> SrcSpan) -> [n] -> RnM ()
+dupNamesErr get_loc names
   = addErrAt big_loc $
     vcat [ptext (sLit "Conflicting definitions for") <+> quotes (ppr (head names)),
   = addErrAt big_loc $
     vcat [ptext (sLit "Conflicting definitions for") <+> quotes (ppr (head names)),
-         locations, descriptor]
+         locations]
   where
     locs      = map get_loc names
     big_loc   = foldr1 combineSrcSpans locs
   where
     locs      = map get_loc names
     big_loc   = foldr1 combineSrcSpans locs
-    one_line  = isOneLineSpan big_loc
-    locations | one_line  = empty 
-             | otherwise = ptext (sLit "Bound at:") <+> 
-                           vcat (map ppr (sortLe (<=) locs))
+    locations = ptext (sLit "Bound at:") <+> vcat (map ppr (sortLe (<=) locs))
 
 kindSigErr :: Outputable a => a -> SDoc
 kindSigErr thing
 
 kindSigErr :: Outputable a => a -> SDoc
 kindSigErr thing