+\begin{code}
+data Provenance
+ = LocalDef -- Defined locally
+
+ | NonLocalDef -- Defined non-locally
+ ImportReason
+
+-- Just used for grouping error messages (in RnEnv.warnUnusedBinds)
+instance Eq Provenance where
+ p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
+
+instance Eq ImportReason where
+ p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
+
+instance Ord Provenance where
+ compare LocalDef LocalDef = EQ
+ compare LocalDef (NonLocalDef _) = LT
+ compare (NonLocalDef _) LocalDef = GT
+
+ compare (NonLocalDef reason1) (NonLocalDef reason2)
+ = compare reason1 reason2
+
+instance Ord ImportReason where
+ compare ImplicitImport ImplicitImport = EQ
+ compare ImplicitImport (UserImport _ _ _) = LT
+ compare (UserImport _ _ _) ImplicitImport = GT
+ compare (UserImport m1 loc1 _) (UserImport m2 loc2 _)
+ = (m1 `compare` m2) `thenCmp` (loc1 `compare` loc2)
+
+
+data ImportReason
+ = UserImport Module SrcLoc Bool -- Imported from module M on line L
+ -- Note the M may well not be the defining module
+ -- for this thing!
+ -- The Bool is true iff the thing was named *explicitly* in the import spec,
+ -- rather than being imported as part of a group; e.g.
+ -- import B
+ -- import C( T(..) )
+ -- Here, everything imported by B, and the constructors of T
+ -- are not named explicitly; only T is named explicitly.
+ -- This info is used when warning of unused names.
+
+ | ImplicitImport -- Imported implicitly for some other reason
+\end{code}
+
+\begin{code}
+hasBetterProv :: Provenance -> Provenance -> Bool
+-- Choose
+-- a local thing over an imported thing
+-- a user-imported thing over a non-user-imported thing
+-- an explicitly-imported thing over an implicitly imported thing
+hasBetterProv LocalDef _ = True
+hasBetterProv (NonLocalDef (UserImport _ _ _ )) (NonLocalDef ImplicitImport) = True
+hasBetterProv _ _ = False
+
+pprNameProvenance :: Name -> Provenance -> SDoc
+pprNameProvenance name LocalDef = ptext SLIT("defined at") <+> ppr (nameSrcLoc name)
+pprNameProvenance name (NonLocalDef why) = sep [ppr_reason why,
+ nest 2 (parens (ppr_defn (nameSrcLoc name)))]
+
+ppr_reason ImplicitImport = ptext SLIT("implicitly imported")
+ppr_reason (UserImport mod loc _) = ptext SLIT("imported from") <+> ppr mod <+> ptext SLIT("at") <+> ppr loc
+
+ppr_defn loc | isGoodSrcLoc loc = ptext SLIT("at") <+> ppr loc
+ | otherwise = empty
+\end{code}