Initial checkin of HetMet / -XModalTypes modifications
[ghc-hetmet.git] / compiler / rename / RnEnv.lhs
index e1d90e8..a5aa5e1 100644 (file)
@@ -1,4 +1,4 @@
-\%
+%
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-2006
 %
 \section[RnEnv]{Environment manipulation for the renamer monad}
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-2006
 %
 \section[RnEnv]{Environment manipulation for the renamer monad}
@@ -8,35 +8,35 @@ module RnEnv (
        newTopSrcBinder, lookupFamInstDeclBndr,
        lookupLocatedTopBndrRn, lookupTopBndrRn,
        lookupLocatedOccRn, lookupOccRn, 
        newTopSrcBinder, lookupFamInstDeclBndr,
        lookupLocatedTopBndrRn, lookupTopBndrRn,
        lookupLocatedOccRn, lookupOccRn, 
-       lookupLocatedGlobalOccRn, lookupGlobalOccRn,
-       lookupLocalDataTcNames, lookupSrcOcc_maybe,
-       lookupSigOccRn,
+        lookupGlobalOccRn, lookupGlobalOccRn_maybe,
+       lookupLocalDataTcNames, lookupSigOccRn,
        lookupFixityRn, lookupTyFixityRn, 
        lookupFixityRn, lookupTyFixityRn, 
-       lookupInstDeclBndr, lookupRecordBndr, lookupConstructorFields,
-       lookupSyntaxName, lookupSyntaxTable, lookupImportedName,
+       lookupInstDeclBndr, lookupSubBndr, lookupConstructorFields,
+       lookupSyntaxName, lookupSyntaxTable, 
        lookupGreRn, lookupGreLocalRn, lookupGreRn_maybe,
        lookupGreRn, lookupGreLocalRn, lookupGreRn_maybe,
-       getLookupOccRn,
+       getLookupOccRn, addUsedRdrNames,
 
 
-       newLocalsRn, newIPNameRn,
-       bindLocalNames, bindLocalNamesFV, 
+       newLocalBndrRn, newLocalBndrsRn, newIPNameRn,
+       bindLocalName, bindLocalNames, bindLocalNamesFV, 
        MiniFixityEnv, emptyFsEnv, extendFsEnv, lookupFsEnv,
        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,
        warnUnusedTopBinds, warnUnusedLocalBinds,
-       dataTcOccs, unknownNameErr, perhapsForallMsg
+       dataTcOccs, unknownNameErr, kindSigErr, perhapsForallMsg
     ) where
 
 #include "HsVersions.h"
 
 import LoadIface       ( loadInterfaceForName, loadSrcInterface )
 import IfaceEnv                ( lookupOrig, newGlobalBinder, newIPName )
     ) where
 
 #include "HsVersions.h"
 
 import LoadIface       ( loadInterfaceForName, loadSrcInterface )
 import IfaceEnv                ( lookupOrig, newGlobalBinder, newIPName )
+import TcEnv           ( getHetMetLevel )
 import HsSyn
 import RdrHsSyn                ( extractHsTyRdrTyVars )
 import RdrName
 import HsSyn
 import RdrHsSyn                ( extractHsTyRdrTyVars )
 import RdrName
@@ -44,49 +44,32 @@ 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, hasKey, forall_tv_RDR )
-import UniqSupply
-import BasicTypes      ( IPName, mapIPName, Fixity )
+import PrelNames        ( mkUnboundName, rOOT_MAIN, consDataConKey, forall_tv_RDR )
+import Unique
+import BasicTypes
 import ErrUtils                ( Message )
 import SrcLoc
 import Outputable
 import Util
 import Maybes
 import ListSetOps      ( removeDups )
 import ErrUtils                ( Message )
 import SrcLoc
 import Outputable
 import Util
 import Maybes
 import ListSetOps      ( removeDups )
-import List            ( nubBy )
 import DynFlags
 import FastString
 import Control.Monad
 import DynFlags
 import FastString
 import Control.Monad
+import Data.List
+import qualified Data.Set as Set
 \end{code}
 
 \begin{code}
 -- XXX
 thenM :: Monad a => a b -> (b -> a c) -> a c
 thenM = (>>=)
 \end{code}
 
 \begin{code}
 -- XXX
 thenM :: Monad a => a b -> (b -> a c) -> a c
 thenM = (>>=)
-
-thenM_ :: Monad a => a b -> a c -> a c
-thenM_ = (>>)
-
-returnM :: Monad m => a -> m a
-returnM = return
-
-mappM :: (Monad m) => (a -> m b) -> [a] -> m [b]
-mappM = mapM
-
-mappM_ :: (Monad m) => (a -> m b) -> [a] -> m ()
-mappM_ = mapM_
-
-checkM :: Monad m => Bool -> m () -> m ()
-checkM = unless
 \end{code}
 
 %*********************************************************
 \end{code}
 
 %*********************************************************
@@ -96,8 +79,8 @@ checkM = unless
 %*********************************************************
 
 \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
@@ -109,13 +92,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 { checkM (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 { checkM (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
@@ -138,7 +123,7 @@ newTopSrcBinder this_mod (L loc rdr_name)
                --TODO, should pass the whole span
 
   | otherwise
                --TODO, should pass the whole span
 
   | otherwise
-  = do { checkM (not (isQual rdr_name))
+  = do { unless (not (isQual rdr_name))
                 (addErrAt loc (badQualBndrErr rdr_name))
                -- Binders should not be qualified; if they are, and with a different
                -- module name, we we get a confusing "M.T is not in scope" error later
                 (addErrAt loc (badQualBndrErr rdr_name))
                -- Binders should not be qualified; if they are, and with a different
                -- module name, we we get a confusing "M.T is not in scope" error later
@@ -151,7 +136,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}
 
 %*********************************************************
@@ -162,13 +148,25 @@ newTopSrcBinder this_mod (L loc rdr_name)
 
 Looking up a name in the RnEnv.
 
 
 Looking up a name in the RnEnv.
 
+Note [Type and class operator definitions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We want to reject all of these unless we have -XTypeOperators (Trac #3265)
+   data a :*: b  = ...
+   class a :*: b where ...
+   data (:*:) a b  = ....
+   class (:*:) a b where ...
+The latter two mean that we are not just looking for a
+*syntactically-infix* declaration, but one that uses an operator
+OccName.  We use OccName.isSymOcc to detect that case, which isn't
+terribly efficient, but there seems to be no better way.
+
 \begin{code}
 lookupTopBndrRn :: RdrName -> RnM Name
 lookupTopBndrRn n = do nopt <- lookupTopBndrRn_maybe n
                        case nopt of 
                          Just n' -> return n'
                          Nothing -> do traceRn $ text "lookupTopBndrRn"
 \begin{code}
 lookupTopBndrRn :: RdrName -> RnM Name
 lookupTopBndrRn n = do nopt <- lookupTopBndrRn_maybe n
                        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
@@ -192,7 +190,7 @@ lookupTopBndrRn_maybe :: RdrName -> RnM (Maybe Name)
 
 lookupTopBndrRn_maybe rdr_name
   | Just name <- isExact_maybe rdr_name
 
 lookupTopBndrRn_maybe rdr_name
   | Just name <- isExact_maybe rdr_name
-  = returnM (Just name)
+  = return (Just name)
 
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name   
        -- This deals with the case of derived bindings, where
 
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name   
        -- This deals with the case of derived bindings, where
@@ -203,14 +201,21 @@ lookupTopBndrRn_maybe rdr_name
         ; return (Just n)}
 
   | otherwise
         ; return (Just n)}
 
   | otherwise
-  = do { mb_gre <- lookupGreLocalRn rdr_name
+  = do {  -- Check for operators in type or class declarations
+           -- See Note [Type and class operator definitions]
+          let occ = rdrNameOcc rdr_name
+        ; when (isTcOcc occ && isSymOcc occ)
+               (do { op_ok <- xoptM Opt_TypeOperators
+                  ; unless op_ok (addErr (opDeclErr rdr_name)) })
+
+       ; mb_gre <- lookupGreLocalRn rdr_name
        ; case mb_gre of
        ; case mb_gre of
-               Nothing  -> returnM Nothing
-               Just gre -> returnM (Just $ gre_name gre) }
+               Nothing  -> return Nothing
+               Just gre -> return (Just $ gre_name gre) }
              
 
 -----------------------------------------------
              
 
 -----------------------------------------------
-lookupInstDeclBndr :: Name -> Located RdrName -> RnM (Located Name)
+lookupInstDeclBndr :: Name -> RdrName -> RnM Name
 -- This is called on the method name on the left-hand side of an 
 -- instance declaration binding. eg.  instance Functor T where
 --                                       fmap = ...
 -- This is called on the method name on the left-hand side of an 
 -- instance declaration binding. eg.  instance Functor T where
 --                                       fmap = ...
@@ -222,40 +227,17 @@ lookupInstDeclBndr :: Name -> Located RdrName -> RnM (Located Name)
 -- name is only in scope qualified.  I.e. even if method op is
 -- in scope as M.op, we still allow plain 'op' on the LHS of
 -- an instance decl
 -- name is only in scope qualified.  I.e. even if method op is
 -- in scope as M.op, we still allow plain 'op' on the LHS of
 -- an instance decl
-lookupInstDeclBndr cls rdr = lookup_located_sub_bndr is_op doc rdr
+lookupInstDeclBndr cls rdr
+  = do { when (isQual rdr)
+                     (addErr (badQualBndrErr rdr)) 
+               -- In an instance decl you aren't allowed
+               -- to use a qualified name for the method
+               -- (Although it'd make perfect sense.)
+       ; lookupSubBndr (ParentIs cls) doc rdr }
   where
     doc = ptext (sLit "method of class") <+> quotes (ppr cls)
   where
     doc = ptext (sLit "method of class") <+> quotes (ppr cls)
-    is_op (GRE {gre_par = ParentIs n}) = n == cls
-    is_op _                            = False
 
 -----------------------------------------------
 
 -----------------------------------------------
-lookupRecordBndr :: Maybe (Located Name) -> Located RdrName -> RnM (Located Name)
--- Used for record construction and pattern matching
--- When the -XDisambiguateRecordFields flag is on, take account of the
--- constructor name to disambiguate which field to use; it's just the
--- same as for instance decls
--- 
--- NB: Consider this:
---     module Foo where { data R = R { fld :: Int } }
---     module Odd where { import Foo; fld x = x { fld = 3 } }
--- Arguably this should work, because the reference to 'fld' is
--- unambiguous because there is only one field id 'fld' in scope.
--- But currently it's rejected.
-lookupRecordBndr Nothing rdr_name
-  = lookupLocatedGlobalOccRn rdr_name
-lookupRecordBndr (Just (L _ data_con)) rdr_name
-  = do         { flag_on <- doptM Opt_DisambiguateRecordFields
-       ; if not flag_on 
-          then lookupLocatedGlobalOccRn rdr_name
-         else do {
-         fields <- lookupConstructorFields data_con
-       ; let is_field gre = gre_name gre `elem` fields
-       ; lookup_located_sub_bndr is_field doc rdr_name
-       }}
-   where
-     doc = ptext (sLit "field of constructor") <+> quotes (ppr data_con)
-
-
 lookupConstructorFields :: Name -> RnM [Name]
 -- Look up the fields of a given constructor
 --   * For constructors from this module, use the record field env,
 lookupConstructorFields :: Name -> RnM [Name]
 -- Look up the fields of a given constructor
 --   * For constructors from this module, use the record field env,
@@ -276,59 +258,96 @@ lookupConstructorFields con_name
             ; return (dataConFieldLabels con) } }
 
 -----------------------------------------------
             ; return (dataConFieldLabels con) } }
 
 -----------------------------------------------
-lookup_located_sub_bndr :: (GlobalRdrElt -> Bool)
-                       -> SDoc -> Located RdrName
-                       -> RnM (Located Name)
-lookup_located_sub_bndr is_good doc rdr_name
-  = wrapLocM (lookup_sub_bndr is_good doc) rdr_name
-
-lookup_sub_bndr :: (GlobalRdrElt -> Bool) -> SDoc -> RdrName -> RnM Name
-lookup_sub_bndr is_good doc rdr_name
-  | isUnqual rdr_name  -- Find all the things the rdr-name maps to
-  = do {               -- and pick the one with the right parent name
+-- Used for record construction and pattern matching
+-- When the -XDisambiguateRecordFields flag is on, take account of the
+-- constructor name to disambiguate which field to use; it's just the
+-- same as for instance decls
+-- 
+-- NB: Consider this:
+--     module Foo where { data R = R { fld :: Int } }
+--     module Odd where { import Foo; fld x = x { fld = 3 } }
+-- Arguably this should work, because the reference to 'fld' is
+-- unambiguous because there is only one field id 'fld' in scope.
+-- But currently it's rejected.
+
+lookupSubBndr :: Parent  -- NoParent   => just look it up as usual
+                        -- ParentIs p => use p to disambiguate
+              -> SDoc -> RdrName 
+              -> RnM Name
+lookupSubBndr parent doc rdr_name
+  | Just n <- isExact_maybe rdr_name   -- This happens in derived code
+  = return n
+
+  | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
+  = lookupOrig rdr_mod rdr_occ
+
+  | otherwise  -- Find all the things the rdr-name maps to
+  = do {       -- and pick the one with the right parent name
        ; env <- getGlobalRdrEnv
        ; env <- getGlobalRdrEnv
-       ; case filter is_good (lookupGlobalRdrEnv env (rdrNameOcc rdr_name)) of
+        ; 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
                -- NB: lookupGlobalRdrEnv, not lookupGRE_RdrName!
                --     The latter does pickGREs, but we want to allow 'x'
                --     even if only 'M.x' is in scope
-           [gre] -> return (gre_name gre)
+           [gre] -> do { addUsedRdrNames (used_rdr_names gre)
+                        ; return (gre_name gre) }
            []    -> do { addErr (unknownSubordinateErr doc rdr_name)
            []    -> do { addErr (unknownSubordinateErr doc rdr_name)
-                       ; traceRn (text "RnEnv.lookup_sub_bndr" <+> ppr rdr_name)
+                       ; traceRn (text "RnEnv.lookup_sub_bndr" <+> (ppr rdr_name $$ ppr gres))
                        ; return (mkUnboundName rdr_name) }
            gres  -> do { addNameClashErrRn rdr_name gres
                        ; return (mkUnboundName rdr_name) }
            gres  -> do { addNameClashErrRn rdr_name gres
-                       ; return (gre_name (head gres)) }
-       }
-
-  | otherwise  -- Occurs in derived instances, where we just
-               -- refer directly to the right method
-  = ASSERT2( not (isQual rdr_name), ppr rdr_name )
-         -- NB: qualified names are rejected by the parser
-    lookupImportedName rdr_name
+                       ; return (gre_name (head gres)) } }
+  where
+    pick NoParent gres         -- Normal lookup 
+      = pickGREs rdr_name gres
+    pick (ParentIs p) gres     -- Disambiguating lookup
+      | isUnqual rdr_name = filter (right_parent p) gres
+      | otherwise         = filter (right_parent p) (pickGREs rdr_name gres)
+
+    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)
 
--- Looking up family names in type instances is a subtle affair.  The family
--- may be imported, in which case we need to lookup the occurence of a global
--- name.  Alternatively, the family may be in the same binding group (and in
--- fact in a declaration processed later), and we need to create a new top
--- source binder.
+-- If the family is declared locally, it will not yet be in the main
+-- environment; hence, we pass in an extra one here, which we check first.
+-- See "Note [Looking up family names in family instances]" in 'RnNames'.
 --
 --
--- So, also this is strictly speaking an occurence, we cannot raise an error
--- message yet for instances without a family declaration.  This will happen
--- during renaming the type instance declaration in RnSource.rnTyClDecl.
---
-lookupFamInstDeclBndr :: Module -> Located RdrName -> RnM Name
-lookupFamInstDeclBndr mod lrdr_name@(L _ rdr_name)
-  = do { mb_gre <- lookupGreRn_maybe rdr_name
-       ; case mb_gre of
-           Just gre -> returnM (gre_name gre)
-          Nothing  -> newTopSrcBinder mod lrdr_name }
+lookupFamInstDeclBndr :: GlobalRdrEnv -> Located RdrName -> RnM Name
+lookupFamInstDeclBndr tyclGroupEnv (L loc rdr_name)
+  = setSrcSpan loc $
+      case lookupGRE_RdrName rdr_name tyclGroupEnv of
+        (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 ->
@@ -340,86 +359,58 @@ 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 -> returnM name
-         Nothing   -> lookupGlobalOccRn rdr_name
+  = do { local_env <- getLocalRdrEnv
+       ; case lookupLocalRdrEnv local_env rdr_name of {
+          Just name -> return name ;
+          Nothing   -> do
+
+       { mb_name <- lookupGlobalOccRn_maybe rdr_name
+       ; case mb_name of {
+               Just n  -> return n ;
+               Nothing -> do
+
+       { -- We allow qualified names on the command line to refer to 
+        --  *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
+       ; is_ghci <- getIsGHCi
+               -- This test is not expensive,
+               -- and only happens for failed lookups
+       ; if isQual rdr_name && allow_qual && is_ghci
+         then lookupQualifiedName rdr_name
+         else unboundName WL_Any rdr_name } } } } }
 
 
-lookupLocatedGlobalOccRn :: Located RdrName -> RnM (Located Name)
-lookupLocatedGlobalOccRn = wrapLocM lookupGlobalOccRn
 
 lookupGlobalOccRn :: RdrName -> RnM Name
 -- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
 
 lookupGlobalOccRn :: RdrName -> RnM Name
 -- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
--- environment.  It's used only for
---     record field names
---     class op names in class and instance decls
-
+-- environment.  Adds an error message if the RdrName is not in scope.
 lookupGlobalOccRn rdr_name
 lookupGlobalOccRn rdr_name
-  | not (isSrcRdrName rdr_name)
-  = lookupImportedName 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 rdr_name
+  | Just n <- isExact_maybe rdr_name   -- This happens in derived code
+  = return (Just n)
 
 
-  | otherwise
-  = do
-       -- First look up the name in the normal environment.
-   mb_gre <- lookupGreRn_maybe rdr_name
-   case mb_gre of {
-       Just gre -> returnM (gre_name gre) ;
-       Nothing   -> do
-
-       -- We allow qualified names on the command line to refer to 
-       --  *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
-               -- This test is not expensive,
-               -- and only happens for failed lookups
-   if isQual rdr_name && allow_qual && mod == iNTERACTIVE
-      then lookupQualifiedName rdr_name
-      else unboundName rdr_name
-  }
-
-lookupImportedName :: RdrName -> TcRnIf m n Name
--- Lookup the occurrence of an imported name
--- The RdrName is *always* qualified or Exact
--- Treat it as an original name, and conjure up the Name
--- Usually it's Exact or Orig, but it can be Qual if it
---     comes from an hi-boot file.  (This minor infelicity is 
---     just to reduce duplication in the parser.)
-lookupImportedName rdr_name
-  | Just n <- isExact_maybe rdr_name 
-       -- This happens in derived code
-  = returnM n
-
-       -- Always Orig, even when reading a .hi-boot file
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
-  = lookupOrig rdr_mod rdr_occ
+  = do { n <- lookupOrig rdr_mod rdr_occ; return (Just n) }
 
   | otherwise
 
   | otherwise
-  = pprPanic "RnEnv.lookupImportedName" (ppr rdr_name)
+  = do { mb_gre <- lookupGreRn_maybe rdr_name
+       ; case mb_gre of
+               Nothing  -> return Nothing
+               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)])
-       ; returnM (mkUnboundName rdr_name) }
 
 --------------------------------------------------
 --     Lookup in the Global RdrEnv of the module
 --------------------------------------------------
 
 
 --------------------------------------------------
 --     Lookup in the Global RdrEnv of the module
 --------------------------------------------------
 
-lookupSrcOcc_maybe :: RdrName -> RnM (Maybe Name)
--- No filter function; does not report an error on failure
-lookupSrcOcc_maybe rdr_name
-  = do { mb_gre <- lookupGreRn_maybe rdr_name
-       ; case mb_gre of
-               Nothing  -> returnM Nothing
-               Just gre -> returnM (Just (gre_name gre)) }
-       
--------------------------
 lookupGreRn_maybe :: RdrName -> RnM (Maybe GlobalRdrElt)
 -- Just look up the RdrName in the GlobalRdrEnv
 lookupGreRn_maybe rdr_name 
 lookupGreRn_maybe :: RdrName -> RnM (Maybe GlobalRdrElt)
 -- Just look up the RdrName in the GlobalRdrEnv
 lookupGreRn_maybe rdr_name 
@@ -433,7 +424,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 }) }}}
 
@@ -452,10 +443,28 @@ lookupGreRn_help :: RdrName                       -- Only used in error message
 lookupGreRn_help rdr_name lookup 
   = do { env <- getGlobalRdrEnv
        ; case lookup env of
 lookupGreRn_help rdr_name lookup 
   = do { env <- getGlobalRdrEnv
        ; case lookup env of
-           []    -> returnM Nothing
-           [gre] -> returnM (Just gre)
+           []    -> return Nothing
+           [gre] -> do { addUsedRdrName gre rdr_name
+                        ; return (Just gre) }
            gres  -> do { addNameClashErrRn rdr_name gres
            gres  -> do { addNameClashErrRn rdr_name gres
-                       ; returnM (Just (head gres)) } }
+                       ; return (Just (head gres)) } }
+
+addUsedRdrName :: GlobalRdrElt -> RdrName -> RnM ()
+-- Record usage of imported RdrNames
+addUsedRdrName gre rdr
+  | isLocalGRE gre = return ()
+  | otherwise      = do { env <- getGblEnv
+                               ; 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.
+addUsedRdrNames rdrs
+  = do { env <- getGblEnv
+       ; updMutVar (tcg_used_rdrnames env)
+                  (\s -> foldr Set.insert s rdrs) }
 
 ------------------------------
 --     GHCi support
 
 ------------------------------
 --     GHCi support
@@ -477,7 +486,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)
@@ -485,6 +494,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
@@ -505,10 +516,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
@@ -518,29 +532,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
@@ -633,23 +647,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}
 
 --------------------------------
@@ -696,7 +704,7 @@ lookupFixityRn name
         loadInterfaceForName doc name  `thenM` \ iface -> do {
           traceRn (text "lookupFixityRn: looking up name in iface cache and found:" <+> 
                    vcat [ppr name, ppr $ mi_fix_fn iface (nameOccName name)]);
         loadInterfaceForName doc name  `thenM` \ iface -> do {
           traceRn (text "lookupFixityRn: looking up name in iface cache and found:" <+> 
                    vcat [ppr name, ppr $ mi_fix_fn iface (nameOccName name)]);
-          returnM (mi_fix_fn iface (nameOccName name))
+          return (mi_fix_fn iface (nameOccName name))
                                                            }
   where
     doc = ptext (sLit "Checking fixity for") <+> ppr name
                                                            }
   where
     doc = ptext (sLit "Checking fixity for") <+> ppr name
@@ -711,7 +719,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
@@ -750,27 +758,27 @@ checks the type of the user thing against the type of the standard thing.
 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
-    else
-       -- Get the similarly named thing from the local environment
-    lookupOccRn (mkRdrUnqual (nameOccName std_name)) `thenM` \ usr_name ->
-    returnM (HsVar usr_name, unitFV usr_name)
-  where
-    normal_case = returnM (HsVar std_name, emptyFVs)
+  = do ec <- getHetMetLevel
+       std_name' <- return $ setNameDepth (length ec) std_name
+       rebindable_on <- xoptM Opt_RebindableSyntax
+       if not rebindable_on
+         then return (HsVar std_name', emptyFVs)
+         else do usr_name <- lookupOccRn (mkRdrUnqual (nameOccName std_name'))
+                 return (HsVar usr_name, unitFV usr_name)
+               -- Get the similarly named thing from the local environment
 
 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
     else
        -- Get the similarly named thing from the local environment
-    mappM (lookupOccRn . mkRdrUnqual . nameOccName) std_names  `thenM` \ usr_names ->
+    mapM (lookupOccRn . mkRdrUnqual . nameOccName) std_names   `thenM` \ usr_names ->
 
 
-    returnM (std_names `zip` map HsVar usr_names, mkFVs usr_names)
+    return (std_names `zip` map HsVar usr_names, mkFVs usr_names)
   where
   where
-    normal_case = returnM (std_names `zip` map HsVar std_names, emptyFVs)
+    normal_case = return (std_names `zip` map HsVar std_names, emptyFVs)
 \end{code}
 
 
 \end{code}
 
 
@@ -781,80 +789,91 @@ lookupSyntaxTable std_names
 %*********************************************************
 
 \begin{code}
 %*********************************************************
 
 \begin{code}
-newLocalsRn :: [Located RdrName] -> RnM [Name]
-newLocalsRn rdr_names_w_loc
-  = newUniqueSupply            `thenM` \ us ->
-    returnM (zipWith mk rdr_names_w_loc (uniqsFromSupply us))
-  where
-    mk (L loc rdr_name) uniq
-       | Just name <- isExact_maybe rdr_name = name
-               -- This happens in code generated by Template Haskell 
-       | otherwise = ASSERT2( isUnqual rdr_name, ppr rdr_name )
-                       -- We only bind unqualified names here
-                       -- lookupRdrEnv doesn't even attempt to look up a qualified RdrName
-                     mkInternalName uniq (rdrNameOcc rdr_name) loc
+newLocalBndrRn :: Located RdrName -> RnM Name
+-- Used for non-top-level binders.  These should
+-- never be qualified.
+newLocalBndrRn (L loc rdr_name)
+  | Just name <- isExact_maybe rdr_name 
+  = return name        -- This happens in code generated by Template Haskell
+               -- although I'm not sure why. Perhpas it's the call
+               -- in RnPat.newName LetMk?
+  | otherwise
+  = do { unless (isUnqual rdr_name)
+               (addErrAt loc (badQualBndrErr rdr_name))
+       ; uniq <- newUnique
+       ; return (mkInternalName uniq (rdrNameOcc rdr_name) loc) }
 
 
----------------------
-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] }
+newLocalBndrsRn :: [Located RdrName] -> RnM [Name]
+newLocalBndrsRn = mapM newLocalBndrRn
 
 ---------------------
 
 ---------------------
-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
-  = checkDupAndShadowedRdrNames doc_str rdr_names_w_loc        `thenM_`
+bindLocatedLocalsRn rdr_names_w_loc enclosed_scope
+  = do { checkDupAndShadowedRdrNames rdr_names_w_loc
 
        -- Make fresh Names and extend the environment
 
        -- Make fresh Names and extend the environment
-    newLocalsRn rdr_names_w_loc                `thenM` \names ->
-    bindLocalNames names (enclosed_scope names)
+       ; names <- newLocalBndrsRn rdr_names_w_loc
+       ; bindLocalNames names (enclosed_scope names) }
 
 bindLocalNames :: [Name] -> RnM a -> RnM a
 bindLocalNames names enclosed_scope
 
 bindLocalNames :: [Name] -> RnM a -> RnM a
 bindLocalNames names enclosed_scope
-  = getLocalRdrEnv             `thenM` \ name_env ->
-    setLocalRdrEnv (extendLocalRdrEnv name_env names)
-                   enclosed_scope
+  = do { name_env <- getLocalRdrEnv
+       ; setLocalRdrEnv (extendLocalRdrEnvList name_env names)
+                       enclosed_scope }
+
+bindLocalName :: Name -> RnM a -> RnM a
+bindLocalName name enclosed_scope
+  = do { name_env <- getLocalRdrEnv
+       ; setLocalRdrEnv (extendLocalRdrEnv name_env 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
-       ; returnM (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) ->
-    returnM (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
-  = let
-       located_tyvars = hsLTyVarLocNames tyvar_names
-    in
-    bindLocatedLocalsRn doc_str located_tyvars $ \ names ->
-    enclosed_scope (zipWith replace tyvar_names names)
-    where 
-       replace (L loc n1) n2 = L loc (replaceTyVarName n1 n2)
+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) }
+  where 
+    replace (L loc n1) n2 = L loc (replaceTyVarName n1 n2)
+    located_tyvars = hsLTyVarLocNames tyvar_names
+    kinded_tyvars  = [n | L _ (KindedTyVar n _) <- tyvar_names]
 
 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
 
 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
-  = 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 
@@ -867,9 +886,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)
@@ -877,13 +894,13 @@ bindPatSigTyVarsFV :: [LHsType RdrName]
 bindPatSigTyVarsFV tys thing_inside
   = bindPatSigTyVars tys       $ \ tvs ->
     thing_inside               `thenM` \ (result,fvs) ->
 bindPatSigTyVarsFV tys thing_inside
   = bindPatSigTyVars tys       $ \ tvs ->
     thing_inside               `thenM` \ (result,fvs) ->
-    returnM (result, fvs `delListFromNameSet` tvs)
+    return (result, fvs `delListFromNameSet` tvs)
 
 bindSigTyVarsFV :: [Name]
                -> RnM (a, FreeVars)
                -> RnM (a, FreeVars)
 bindSigTyVarsFV tvs thing_inside
 
 bindSigTyVarsFV :: [Name]
                -> 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
@@ -894,38 +911,52 @@ 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
-    mappM_ (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
-    mappM_ (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)
-       ; mappM_ 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)
   where
     check_shadow (loc, occ)
+        | startsWithUnderscore occ = return () -- Do not report shadowing for "_x"
+                                               -- See Trac #3262
        | Just n <- mb_local = complain [ptext (sLit "bound at") <+> ppr (nameSrcLoc n)]
        | otherwise = do { gres' <- filterM is_shadowed_gre gres
                         ; complain (map pprNameProvenance gres') }
        where
          complain []      = return ()
        | Just n <- mb_local = complain [ptext (sLit "bound at") <+> ppr (nameSrcLoc n)]
        | otherwise = do { gres' <- filterM is_shadowed_gre gres
                         ; 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
@@ -936,7 +967,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
@@ -951,16 +982,175 @@ 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))
+    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 :: (a -> RnM (b, FreeVars)) -> [a] -> RnM ([b], FreeVars)
-mapFvRn f xs = do stuff <- mappM f xs
+mapFvRn f xs = do stuff <- mapM f xs
                   case unzip stuff of
                   case unzip stuff of
-                      (ys, fvs_s) -> returnM (ys, plusFVs fvs_s)
+                      (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; 
 
 -- because some of the rename functions are CPSed:
 -- maps the function across the list from left to right; 
@@ -982,22 +1172,19 @@ mapFvRnCPS f (x:xs) cont = f x              $ \ x' ->
 %************************************************************************
 
 \begin{code}
 %************************************************************************
 
 \begin{code}
-warnUnusedModules :: [(ModuleName,SrcSpan)] -> RnM ()
-warnUnusedModules mods
-  = ifOptM Opt_WarnUnusedImports (mappM_ 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
@@ -1005,7 +1192,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
@@ -1018,18 +1205,18 @@ warnUnusedLocals names
  = warnUnusedBinds [(n,LocalDef) | n<-names]
 
 warnUnusedBinds :: [(Name,Provenance)] -> RnM ()
  = warnUnusedBinds [(n,LocalDef) | n<-names]
 
 warnUnusedBinds :: [(Name,Provenance)] -> RnM ()
-warnUnusedBinds names  = mappM_ warnUnusedName (filter reportable names)
+warnUnusedBinds names  = mapM_ warnUnusedName (filter reportable names)
  where reportable (name,_) 
        | isWiredInName name = False    -- Don't report unused wired-in names
                                        -- Otherwise we get a zillion warnings
                                        -- from Data.Tuple
  where reportable (name,_) 
        | isWiredInName name = False    -- Don't report unused wired-in names
                                        -- Otherwise we get a zillion warnings
                                        -- from Data.Tuple
-       | otherwise = reportIfUnused (nameOccName name)
+       | otherwise = not (startsWithUnderscore (nameOccName name))
 
 -------------------------
 
 warnUnusedName :: (Name, Provenance) -> RnM ()
 warnUnusedName (name, LocalDef)
 
 -------------------------
 
 warnUnusedName :: (Name, Provenance) -> RnM ()
 warnUnusedName (name, LocalDef)
-  = addUnusedWarning name (srcLocSpan (nameSrcLoc name)) 
+  = addUnusedWarning name (nameSrcSpan name)
                     (ptext (sLit "Defined but not used"))
 
 warnUnusedName (name, Imported is)
                     (ptext (sLit "Defined but not used"))
 
 warnUnusedName (name, Imported is)
@@ -1058,28 +1245,17 @@ 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 
-  = vcat [ ptext (sLit "Perhaps you intended to use -XRankNTypes or similar flag")
+  = vcat [ ptext (sLit "Perhaps you intended to use -XExplicitForAll or similar flag")
         , ptext (sLit "to enable explicit-forall syntax: forall <tvs>. <type>")]
 
 unknownSubordinateErr :: SDoc -> RdrName -> SDoc
         , ptext (sLit "to enable explicit-forall syntax: forall <tvs>. <type>")]
 
 unknownSubordinateErr :: SDoc -> RdrName -> SDoc
@@ -1092,20 +1268,28 @@ 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
+  = hang (ptext (sLit "Illegal kind signature for") <+> quotes (ppr thing))
+       2 (ptext (sLit "Perhaps you intended to use -XKindSignatures"))
+
 
 badQualBndrErr :: RdrName -> SDoc
 badQualBndrErr rdr_name
   = ptext (sLit "Qualified name in binding position:") <+> ppr rdr_name
 
 badQualBndrErr :: RdrName -> SDoc
 badQualBndrErr rdr_name
   = ptext (sLit "Qualified name in binding position:") <+> ppr rdr_name
+
+opDeclErr :: RdrName -> SDoc
+opDeclErr n 
+  = hang (ptext (sLit "Illegal declaration of a type or class operator") <+> quotes (ppr n))
+       2 (ptext (sLit "Use -XTypeOperators to declare operators in type and declarations"))
 \end{code}
 \end{code}