{-# LANGUAGE PatternSynonyms #-}

{-

This module contains helper functions for reporting and creating
unbound variables.

-}
module GHC.Rename.Unbound
   ( mkUnboundName
   , mkUnboundNameRdr
   , mkUnboundGRE
   , mkUnboundGRERdr
   , isUnboundName
   , reportUnboundName
   , reportUnboundName'
   , unknownNameSuggestions
   , similarNameSuggestions
   , fieldSelectorSuggestions
   , WhatLooking(..)
   , WhereLooking(..)
   , LookingFor(..)
   , unboundName
   , unboundNameX
   , unboundTermNameInTypes
   , IsTermInTypes(..)
   , notInScopeErr
   , nameSpacesRelated
   , termNameInType
   )
where

import GHC.Prelude

import GHC.Driver.DynFlags
import GHC.Driver.Ppr

import GHC.Tc.Errors.Types
import GHC.Tc.Utils.Monad
import GHC.Builtin.Names ( mkUnboundName, isUnboundName, getUnique)
import GHC.Utils.Misc
import GHC.Utils.Panic (panic)

import GHC.Data.Maybe
import GHC.Data.FastString

import qualified GHC.LanguageExtensions as LangExt

import GHC.Types.Hint
  ( GhcHint (SuggestExtension, RemindFieldSelectorSuppressed, ImportSuggestion, SuggestSimilarNames)
  , LanguageExtensionHint (SuggestSingleExtension)
  , ImportSuggestion(..), SimilarName(..), HowInScope(..) )
import GHC.Types.SrcLoc as SrcLoc
import GHC.Types.Name
import GHC.Types.Name.Reader
import GHC.Types.Unique.DFM (udfmToList)

import GHC.Unit.Module
import GHC.Unit.Module.Imported
import GHC.Unit.Home.ModInfo

import GHC.Data.Bag
import GHC.Utils.Outputable (empty)

import Data.List (sortBy, partition, nub)
import Data.List.NonEmpty ( pattern (:|), NonEmpty )
import Data.Function ( on )
import qualified Data.Semigroup as S
import qualified Data.Map as M

{-
************************************************************************
*                                                                      *
               What to do when a lookup fails
*                                                                      *
************************************************************************
-}

-- What kind of suggestion are we looking for? #19843
data WhatLooking = WL_Anything    -- Any binding
                 | WL_Constructor -- Constructors and pattern synonyms
                        -- E.g. in K { f1 = True }, if K is not in scope,
                        -- suggest only constructors
                 | WL_RecField    -- Record fields
                        -- E.g. in K { f1 = True, f2 = False }, if f2 is not in
                        -- scope, suggest only constructor fields
                 | WL_None        -- No suggestions
                        -- WS_None is used for rebindable syntax, where there
                        -- is no point in suggesting alternative spellings
                 deriving WhatLooking -> WhatLooking -> Bool
(WhatLooking -> WhatLooking -> Bool)
-> (WhatLooking -> WhatLooking -> Bool) -> Eq WhatLooking
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WhatLooking -> WhatLooking -> Bool
== :: WhatLooking -> WhatLooking -> Bool
$c/= :: WhatLooking -> WhatLooking -> Bool
/= :: WhatLooking -> WhatLooking -> Bool
Eq

data WhereLooking = WL_Anywhere   -- Any binding
                  | WL_Global     -- Any top-level binding (local or imported)
                  | WL_LocalTop   -- Any top-level binding in this module
                  | WL_LocalOnly
                        -- Only local bindings
                        -- (pattern synonyms declarations,
                        -- see Note [Renaming pattern synonym variables]
                        -- in GHC.Rename.Bind)

data LookingFor = LF { LookingFor -> WhatLooking
lf_which :: WhatLooking
                     , LookingFor -> WhereLooking
lf_where :: WhereLooking
                     }

data IsTermInTypes = UnknownTermInTypes RdrName | TermInTypes RdrName | NoTermInTypes

mkUnboundNameRdr :: RdrName -> Name
mkUnboundNameRdr :: RdrName -> Name
mkUnboundNameRdr RdrName
rdr = OccName -> Name
mkUnboundName (RdrName -> OccName
rdrNameOcc RdrName
rdr)

mkUnboundGRE :: OccName -> GlobalRdrElt
mkUnboundGRE :: OccName -> GlobalRdrElt
mkUnboundGRE OccName
occ = GREInfo -> Parent -> Name -> GlobalRdrElt
mkLocalGRE GREInfo
UnboundGRE Parent
NoParent (Name -> GlobalRdrElt) -> Name -> GlobalRdrElt
forall a b. (a -> b) -> a -> b
$ OccName -> Name
mkUnboundName OccName
occ

mkUnboundGRERdr :: RdrName -> GlobalRdrElt
mkUnboundGRERdr :: RdrName -> GlobalRdrElt
mkUnboundGRERdr RdrName
rdr = GREInfo -> Parent -> Name -> GlobalRdrElt
mkLocalGRE GREInfo
UnboundGRE Parent
NoParent (Name -> GlobalRdrElt) -> Name -> GlobalRdrElt
forall a b. (a -> b) -> a -> b
$ RdrName -> Name
mkUnboundNameRdr RdrName
rdr

reportUnboundName' :: WhatLooking -> RdrName -> RnM Name
reportUnboundName' :: WhatLooking -> RdrName -> RnM Name
reportUnboundName' WhatLooking
what_look RdrName
rdr = LookingFor -> RdrName -> RnM Name
unboundName (WhatLooking -> WhereLooking -> LookingFor
LF WhatLooking
what_look WhereLooking
WL_Anywhere) RdrName
rdr

reportUnboundName :: RdrName -> RnM Name
reportUnboundName :: RdrName -> RnM Name
reportUnboundName = WhatLooking -> RdrName -> RnM Name
reportUnboundName' WhatLooking
WL_Anything

unboundName :: LookingFor -> RdrName -> RnM Name
unboundName :: LookingFor -> RdrName -> RnM Name
unboundName LookingFor
lf RdrName
rdr = LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameX LookingFor
lf RdrName
rdr []

unboundNameX :: LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameX :: LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameX LookingFor
looking_for RdrName
rdr_name [GhcHint]
hints
  = IsTermInTypes -> LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameOrTermInType IsTermInTypes
NoTermInTypes LookingFor
looking_for RdrName
rdr_name [GhcHint]
hints

unboundTermNameInTypes :: LookingFor -> RdrName -> RdrName  -> RnM Name
unboundTermNameInTypes :: LookingFor -> RdrName -> RdrName -> RnM Name
unboundTermNameInTypes LookingFor
looking_for RdrName
rdr_name RdrName
demoted_rdr_name
  = IsTermInTypes -> LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameOrTermInType (RdrName -> IsTermInTypes
UnknownTermInTypes RdrName
demoted_rdr_name) LookingFor
looking_for RdrName
rdr_name []

-- Catches imported qualified terms in type signatures
-- with proper error message and suggestions
termNameInType :: LookingFor -> RdrName -> RdrName -> [GhcHint] -> RnM Name
termNameInType :: LookingFor -> RdrName -> RdrName -> [GhcHint] -> RnM Name
termNameInType LookingFor
looking_for RdrName
rdr_name RdrName
demoted_rdr_name [GhcHint]
external_hints
  = IsTermInTypes -> LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameOrTermInType (RdrName -> IsTermInTypes
TermInTypes RdrName
demoted_rdr_name) LookingFor
looking_for RdrName
rdr_name [GhcHint]
external_hints

unboundNameOrTermInType :: IsTermInTypes -> LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameOrTermInType :: IsTermInTypes -> LookingFor -> RdrName -> [GhcHint] -> RnM Name
unboundNameOrTermInType IsTermInTypes
if_term_in_type LookingFor
looking_for RdrName
rdr_name [GhcHint]
hints
  = do  { dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
        ; let show_helpful_errors = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_HelpfulErrors DynFlags
dflags
        ; if not show_helpful_errors
          then addErr $ make_error [] hints
          else do { local_env  <- getLocalRdrEnv
                  ; global_env <- getGlobalRdrEnv
                  ; impInfo <- getImports
                  ; currmod <- getModule
                  ; hpt <- getHpt
                  ; let (imp_errs, suggs) =
                          unknownNameSuggestions_ looking_for
                            dflags hpt currmod global_env local_env impInfo
                            rdr_name
                  ; addErr $
                      make_error imp_errs (hints ++ suggs) }
        ; return (mkUnboundNameRdr rdr_name) }
    where
      name_to_search :: RdrName
name_to_search = case IsTermInTypes
if_term_in_type of
        IsTermInTypes
NoTermInTypes                   -> RdrName
rdr_name
        UnknownTermInTypes RdrName
demoted_name -> RdrName
demoted_name
        TermInTypes RdrName
demoted_name        -> RdrName
demoted_name

      err :: NotInScopeError
err = WhereLooking -> RdrName -> NotInScopeError
notInScopeErr (LookingFor -> WhereLooking
lf_where LookingFor
looking_for) RdrName
name_to_search

      make_error :: [ImportError] -> [GhcHint] -> TcRnMessage
make_error [ImportError]
imp_errs [GhcHint]
hints = case IsTermInTypes
if_term_in_type of
        TermInTypes RdrName
demoted_name -> RdrName -> [GhcHint] -> TcRnMessage
TcRnTermNameInType RdrName
demoted_name [GhcHint]
hints
        IsTermInTypes
_ -> NotInScopeError
-> RdrName -> [ImportError] -> [GhcHint] -> TcRnMessage
TcRnNotInScope NotInScopeError
err RdrName
name_to_search [ImportError]
imp_errs [GhcHint]
hints

notInScopeErr :: WhereLooking -> RdrName -> NotInScopeError
notInScopeErr :: WhereLooking -> RdrName -> NotInScopeError
notInScopeErr WhereLooking
where_look RdrName
rdr_name
  | Just Name
name <- RdrName -> Maybe Name
isExact_maybe RdrName
rdr_name
  = Name -> NotInScopeError
NoExactName Name
name
  | WhereLooking
WL_LocalTop <- WhereLooking
where_look
  = NotInScopeError
NoTopLevelBinding
  | Bool
otherwise
  = NotInScopeError
NotInScope

-- | Called from the typechecker ("GHC.Tc.Errors") when we find an unbound variable
unknownNameSuggestions :: LocalRdrEnv -> WhatLooking -> RdrName -> RnM ([ImportError], [GhcHint])
unknownNameSuggestions :: LocalRdrEnv
-> WhatLooking -> RdrName -> RnM ([ImportError], [GhcHint])
unknownNameSuggestions LocalRdrEnv
lcl_env WhatLooking
what_look RdrName
tried_rdr_name =
  do { dflags  <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
     ; hpt     <- getHpt
     ; rdr_env <- getGlobalRdrEnv
     ; imp_info <- getImports
     ; curr_mod <- getModule
     ; return $
        unknownNameSuggestions_
          (LF what_look WL_Anywhere)
          dflags hpt curr_mod rdr_env lcl_env imp_info tried_rdr_name }

unknownNameSuggestions_ :: LookingFor -> DynFlags
                       -> HomePackageTable -> Module
                       -> GlobalRdrEnv -> LocalRdrEnv -> ImportAvails
                       -> RdrName -> ([ImportError], [GhcHint])
unknownNameSuggestions_ :: LookingFor
-> DynFlags
-> HomePackageTable
-> Module
-> GlobalRdrEnv
-> LocalRdrEnv
-> ImportAvails
-> RdrName
-> ([ImportError], [GhcHint])
unknownNameSuggestions_ LookingFor
looking_for DynFlags
dflags HomePackageTable
hpt Module
curr_mod GlobalRdrEnv
global_env LocalRdrEnv
local_env
                          ImportAvails
imports RdrName
tried_rdr_name = ([ImportError]
imp_errs, [GhcHint]
suggs)
  where
    suggs :: [GhcHint]
suggs = [[GhcHint]] -> [GhcHint]
forall a. Monoid a => [a] -> a
mconcat
      [ (NonEmpty SimilarName -> GhcHint) -> [SimilarName] -> [GhcHint]
forall a b. (NonEmpty a -> b) -> [a] -> [b]
if_ne (RdrName -> NonEmpty SimilarName -> GhcHint
SuggestSimilarNames RdrName
tried_rdr_name) ([SimilarName] -> [GhcHint]) -> [SimilarName] -> [GhcHint]
forall a b. (a -> b) -> a -> b
$
          LookingFor
-> DynFlags
-> GlobalRdrEnv
-> LocalRdrEnv
-> RdrName
-> [SimilarName]
similarNameSuggestions LookingFor
looking_for DynFlags
dflags GlobalRdrEnv
global_env LocalRdrEnv
local_env RdrName
tried_rdr_name
      , (ImportSuggestion -> GhcHint) -> [ImportSuggestion] -> [GhcHint]
forall a b. (a -> b) -> [a] -> [b]
map (OccName -> ImportSuggestion -> GhcHint
ImportSuggestion (OccName -> ImportSuggestion -> GhcHint)
-> OccName -> ImportSuggestion -> GhcHint
forall a b. (a -> b) -> a -> b
$ RdrName -> OccName
rdrNameOcc RdrName
tried_rdr_name) [ImportSuggestion]
imp_suggs
      , RdrName -> [GhcHint]
extensionSuggestions RdrName
tried_rdr_name
      , GlobalRdrEnv -> RdrName -> [GhcHint]
fieldSelectorSuggestions GlobalRdrEnv
global_env RdrName
tried_rdr_name ]
    ([ImportError]
imp_errs, [ImportSuggestion]
imp_suggs) = LookingFor
-> GlobalRdrEnv
-> HomePackageTable
-> Module
-> ImportAvails
-> RdrName
-> ([ImportError], [ImportSuggestion])
importSuggestions LookingFor
looking_for GlobalRdrEnv
global_env HomePackageTable
hpt Module
curr_mod ImportAvails
imports RdrName
tried_rdr_name

    if_ne :: (NonEmpty a -> b) -> [a] -> [b]
    if_ne :: forall a b. (NonEmpty a -> b) -> [a] -> [b]
if_ne NonEmpty a -> b
_ []       = []
    if_ne NonEmpty a -> b
f (a
a : [a]
as) = [NonEmpty a -> b
f (a
a a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| [a]
as)]

-- | When the name is in scope as field whose selector has been suppressed by
-- NoFieldSelectors, display a helpful message explaining this.
fieldSelectorSuggestions :: GlobalRdrEnv -> RdrName -> [GhcHint]
fieldSelectorSuggestions :: GlobalRdrEnv -> RdrName -> [GhcHint]
fieldSelectorSuggestions GlobalRdrEnv
global_env RdrName
tried_rdr_name
  | [GlobalRdrElt] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [GlobalRdrElt]
gres = []
  | Bool
otherwise = [RdrName -> [Name] -> GhcHint
RemindFieldSelectorSuppressed RdrName
tried_rdr_name [Name]
parents]
  where
    gres :: [GlobalRdrElt]
gres = (GlobalRdrElt -> Bool) -> [GlobalRdrElt] -> [GlobalRdrElt]
forall a. (a -> Bool) -> [a] -> [a]
filter GlobalRdrElt -> Bool
isNoFieldSelectorGRE
         ([GlobalRdrElt] -> [GlobalRdrElt])
-> [GlobalRdrElt] -> [GlobalRdrElt]
forall a b. (a -> b) -> a -> b
$ GlobalRdrEnv -> LookupGRE GREInfo -> [GlobalRdrElt]
forall info.
GlobalRdrEnvX info -> LookupGRE info -> [GlobalRdrEltX info]
lookupGRE GlobalRdrEnv
global_env (RdrName -> WhichGREs GREInfo -> LookupGRE GREInfo
forall info. RdrName -> WhichGREs info -> LookupGRE info
LookupRdrName RdrName
tried_rdr_name WhichGREs GREInfo
AllRelevantGREs)
    parents :: [Name]
parents = [ Name
parent | ParentIs Name
parent <- (GlobalRdrElt -> Parent) -> [GlobalRdrElt] -> [Parent]
forall a b. (a -> b) -> [a] -> [b]
map GlobalRdrElt -> Parent
forall info. GlobalRdrEltX info -> Parent
greParent [GlobalRdrElt]
gres ]

similarNameSuggestions :: LookingFor -> DynFlags
                       -> GlobalRdrEnv -> LocalRdrEnv
                       -> RdrName -> [SimilarName]
similarNameSuggestions :: LookingFor
-> DynFlags
-> GlobalRdrEnv
-> LocalRdrEnv
-> RdrName
-> [SimilarName]
similarNameSuggestions looking_for :: LookingFor
looking_for@(LF WhatLooking
what_look WhereLooking
where_look) DynFlags
dflags GlobalRdrEnv
global_env
                       LocalRdrEnv
local_env RdrName
tried_rdr_name
  = String -> [(String, SimilarName)] -> [SimilarName]
forall a. String -> [(String, a)] -> [a]
fuzzyLookup (DynFlags -> RdrName -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags RdrName
tried_rdr_name) [(String, SimilarName)]
all_possibilities
  where
    all_possibilities :: [(String, SimilarName)]
    all_possibilities :: [(String, SimilarName)]
all_possibilities = case WhatLooking
what_look of
      WhatLooking
WL_None -> []
      WhatLooking
_ -> [ (DynFlags -> RdrName -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags RdrName
r, RdrName -> Maybe HowInScope -> SimilarName
SimilarRdrName RdrName
r (HowInScope -> Maybe HowInScope
forall a. a -> Maybe a
Just (HowInScope -> Maybe HowInScope) -> HowInScope -> Maybe HowInScope
forall a b. (a -> b) -> a -> b
$ SrcSpan -> HowInScope
LocallyBoundAt SrcSpan
loc))
           | (RdrName
r,SrcSpan
loc) <- LocalRdrEnv -> [(RdrName, SrcSpan)]
local_possibilities LocalRdrEnv
local_env ]
        [(String, SimilarName)]
-> [(String, SimilarName)] -> [(String, SimilarName)]
forall a. [a] -> [a] -> [a]
++ [ (DynFlags -> RdrName -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags RdrName
r, SimilarName
rp) | (RdrName
r, SimilarName
rp) <- GlobalRdrEnv -> [(RdrName, SimilarName)]
global_possibilities GlobalRdrEnv
global_env ]

    tried_occ :: OccName
tried_occ     = RdrName -> OccName
rdrNameOcc RdrName
tried_rdr_name
    tried_is_sym :: Bool
tried_is_sym  = OccName -> Bool
isSymOcc OccName
tried_occ
    tried_ns :: NameSpace
tried_ns      = OccName -> NameSpace
occNameSpace OccName
tried_occ
    tried_is_qual :: Bool
tried_is_qual = RdrName -> Bool
isQual RdrName
tried_rdr_name

    correct_name_space :: OccName -> Bool
correct_name_space OccName
occ =
      (DynFlags -> WhatLooking -> NameSpace -> NameSpace -> Bool
nameSpacesRelated DynFlags
dflags WhatLooking
what_look NameSpace
tried_ns (OccName -> NameSpace
occNameSpace OccName
occ))
      Bool -> Bool -> Bool
&& OccName -> Bool
isSymOcc OccName
occ Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
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 :: Bool
local_ok = case WhereLooking
where_look of { WhereLooking
WL_Anywhere  -> Bool
True
                                  ; WhereLooking
WL_LocalOnly -> Bool
True
                                  ; WhereLooking
_            -> Bool
False }

    local_possibilities :: LocalRdrEnv -> [(RdrName, SrcSpan)]
    local_possibilities :: LocalRdrEnv -> [(RdrName, SrcSpan)]
local_possibilities LocalRdrEnv
env
      | Bool
tried_is_qual = []
      | Bool -> Bool
not Bool
local_ok  = []
      | Bool
otherwise     = [ (OccName -> RdrName
mkRdrUnqual OccName
occ, Name -> SrcSpan
nameSrcSpan Name
name)
                        | Name
name <- LocalRdrEnv -> [Name]
localRdrEnvElts LocalRdrEnv
env
                        , let occ :: OccName
occ = Name -> OccName
nameOccName Name
name
                        , OccName -> Bool
correct_name_space OccName
occ]

    global_possibilities :: GlobalRdrEnv -> [(RdrName, SimilarName)]
    global_possibilities :: GlobalRdrEnv -> [(RdrName, SimilarName)]
global_possibilities GlobalRdrEnv
global_env
      | Bool
tried_is_qual = [ (RdrName
rdr_qual, RdrName -> Maybe HowInScope -> SimilarName
SimilarRdrName RdrName
rdr_qual (HowInScope -> Maybe HowInScope
forall a. a -> Maybe a
Just HowInScope
how))
                        | GlobalRdrElt
gre <- GlobalRdrEnv -> [GlobalRdrElt]
forall info. GlobalRdrEnvX info -> [GlobalRdrEltX info]
globalRdrEnvElts GlobalRdrEnv
global_env
                        , LookingFor -> GlobalRdrElt -> Bool
isGreOk LookingFor
looking_for GlobalRdrElt
gre
                        , let occ :: OccName
occ = GlobalRdrElt -> OccName
forall info. GlobalRdrEltX info -> OccName
greOccName GlobalRdrElt
gre
                        , OccName -> Bool
correct_name_space OccName
occ
                        , (ModuleName
mod, HowInScope
how) <- GlobalRdrElt -> [(ModuleName, HowInScope)]
qualsInScope GlobalRdrElt
gre
                        , let rdr_qual :: RdrName
rdr_qual = ModuleName -> OccName -> RdrName
mkRdrQual ModuleName
mod OccName
occ ]

      | Bool
otherwise = [ (RdrName
rdr_unqual, SimilarName
sim)
                    | GlobalRdrElt
gre <- GlobalRdrEnv -> [GlobalRdrElt]
forall info. GlobalRdrEnvX info -> [GlobalRdrEltX info]
globalRdrEnvElts GlobalRdrEnv
global_env
                    , LookingFor -> GlobalRdrElt -> Bool
isGreOk LookingFor
looking_for GlobalRdrElt
gre
                    , let occ :: OccName
occ = GlobalRdrElt -> OccName
forall info. GlobalRdrEltX info -> OccName
greOccName GlobalRdrElt
gre
                          rdr_unqual :: RdrName
rdr_unqual = OccName -> RdrName
mkRdrUnqual OccName
occ
                    , OccName -> Bool
correct_name_space OccName
occ
                    , SimilarName
sim <- case (GlobalRdrElt -> [HowInScope]
unquals_in_scope GlobalRdrElt
gre, GlobalRdrElt -> [SimilarName]
quals_only GlobalRdrElt
gre) of
                                (HowInScope
how:[HowInScope]
_, [SimilarName]
_)    -> [ RdrName -> Maybe HowInScope -> SimilarName
SimilarRdrName RdrName
rdr_unqual (HowInScope -> Maybe HowInScope
forall a. a -> Maybe a
Just HowInScope
how) ]
                                ([],    SimilarName
pr:[SimilarName]
_) -> [ SimilarName
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 :: GlobalRdrElt -> [HowInScope]
    unquals_in_scope :: GlobalRdrElt -> [HowInScope]
unquals_in_scope (gre :: GlobalRdrElt
gre@GRE { gre_lcl :: forall info. GlobalRdrEltX info -> Bool
gre_lcl = Bool
lcl, gre_imp :: forall info. GlobalRdrEltX info -> Bag ImportSpec
gre_imp = Bag ImportSpec
is })
      | Bool
lcl       = [ SrcSpan -> HowInScope
LocallyBoundAt (GlobalRdrElt -> SrcSpan
forall info. GlobalRdrEltX info -> SrcSpan
greDefinitionSrcSpan GlobalRdrElt
gre) ]
      | Bool
otherwise = [ ImpDeclSpec -> HowInScope
ImportedBy ImpDeclSpec
ispec
                    | ImportSpec
i <- Bag ImportSpec -> [ImportSpec]
forall a. Bag a -> [a]
bagToList Bag ImportSpec
is, let ispec :: ImpDeclSpec
ispec = ImportSpec -> ImpDeclSpec
is_decl ImportSpec
i
                    , Bool -> Bool
not (ImpDeclSpec -> Bool
is_qual ImpDeclSpec
ispec) ]


    --------------------
    quals_only :: GlobalRdrElt -> [SimilarName]
    -- Ones for which *only* the qualified version is in scope
    quals_only :: GlobalRdrElt -> [SimilarName]
quals_only (gre :: GlobalRdrElt
gre@GRE { gre_imp :: forall info. GlobalRdrEltX info -> Bag ImportSpec
gre_imp = Bag ImportSpec
is })
      = [ (RdrName -> Maybe HowInScope -> SimilarName
SimilarRdrName (ModuleName -> OccName -> RdrName
mkRdrQual (ImpDeclSpec -> ModuleName
is_as ImpDeclSpec
ispec) (GlobalRdrElt -> OccName
forall info. GlobalRdrEltX info -> OccName
greOccName GlobalRdrElt
gre)) (HowInScope -> Maybe HowInScope
forall a. a -> Maybe a
Just (HowInScope -> Maybe HowInScope) -> HowInScope -> Maybe HowInScope
forall a b. (a -> b) -> a -> b
$ ImpDeclSpec -> HowInScope
ImportedBy ImpDeclSpec
ispec))
        | ImportSpec
i <- Bag ImportSpec -> [ImportSpec]
forall a. Bag a -> [a]
bagToList Bag ImportSpec
is, let ispec :: ImpDeclSpec
ispec = ImportSpec -> ImpDeclSpec
is_decl ImportSpec
i, ImpDeclSpec -> Bool
is_qual ImpDeclSpec
ispec ]


-- | Generate errors and helpful suggestions if a qualified name Mod.foo is not in scope.
importSuggestions :: LookingFor
                  -> GlobalRdrEnv
                  -> HomePackageTable -> Module
                  -> ImportAvails -> RdrName -> ([ImportError], [ImportSuggestion])
importSuggestions :: LookingFor
-> GlobalRdrEnv
-> HomePackageTable
-> Module
-> ImportAvails
-> RdrName
-> ([ImportError], [ImportSuggestion])
importSuggestions LookingFor
looking_for GlobalRdrEnv
global_env HomePackageTable
hpt Module
currMod ImportAvails
imports RdrName
rdr_name
  | WhereLooking
WL_LocalOnly <- LookingFor -> WhereLooking
lf_where LookingFor
looking_for       = ([], [])
  | WhereLooking
WL_LocalTop  <- LookingFor -> WhereLooking
lf_where LookingFor
looking_for       = ([], [])
  | Bool -> Bool
not (RdrName -> Bool
isQual RdrName
rdr_name Bool -> Bool -> Bool
|| RdrName -> Bool
isUnqual RdrName
rdr_name) = ([], [])
  | [(Module, ImportedModsVal)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Module, ImportedModsVal)]
interesting_imports
  , Just ModuleName
name <- Maybe ModuleName
mod_name
  , ModuleName -> Bool
show_not_imported_line ModuleName
name
  = ([ModuleName -> ImportError
MissingModule ModuleName
name], [])
  | Bool
is_qualified
  , [(Module, ImportedModsVal)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Module, ImportedModsVal)]
helpful_imports
  , (Module
mod : [Module]
mods) <- ((Module, ImportedModsVal) -> Module)
-> [(Module, ImportedModsVal)] -> [Module]
forall a b. (a -> b) -> [a] -> [b]
map (Module, ImportedModsVal) -> Module
forall a b. (a, b) -> a
fst [(Module, ImportedModsVal)]
interesting_imports
  = ([NonEmpty Module -> OccName -> ImportError
ModulesDoNotExport (Module
mod Module -> [Module] -> NonEmpty Module
forall a. a -> [a] -> NonEmpty a
:| [Module]
mods) OccName
occ_name], [])
  | (Module, ImportedModsVal)
mod : [(Module, ImportedModsVal)]
mods <- [(Module, ImportedModsVal)]
helpful_imports_non_hiding
  = ([], [NonEmpty (Module, ImportedModsVal) -> ImportSuggestion
CouldImportFrom ((Module, ImportedModsVal)
mod (Module, ImportedModsVal)
-> [(Module, ImportedModsVal)]
-> NonEmpty (Module, ImportedModsVal)
forall a. a -> [a] -> NonEmpty a
:| [(Module, ImportedModsVal)]
mods)])
  | (Module, ImportedModsVal)
mod : [(Module, ImportedModsVal)]
mods <- [(Module, ImportedModsVal)]
helpful_imports_hiding
  = ([], [NonEmpty (Module, ImportedModsVal) -> ImportSuggestion
CouldUnhideFrom ((Module, ImportedModsVal)
mod (Module, ImportedModsVal)
-> [(Module, ImportedModsVal)]
-> NonEmpty (Module, ImportedModsVal)
forall a. a -> [a] -> NonEmpty a
:| [(Module, ImportedModsVal)]
mods)])
  | Bool
otherwise
  = ([], [])
 where
  is_qualified :: Bool
is_qualified = RdrName -> Bool
isQual RdrName
rdr_name
  (Maybe ModuleName
mod_name, OccName
occ_name) = case RdrName
rdr_name of
    Unqual OccName
occ_name        -> (Maybe ModuleName
forall a. Maybe a
Nothing, OccName
occ_name)
    Qual ModuleName
mod_name OccName
occ_name -> (ModuleName -> Maybe ModuleName
forall a. a -> Maybe a
Just ModuleName
mod_name, OccName
occ_name)
    RdrName
_                      -> String -> (Maybe ModuleName, OccName)
forall a. HasCallStack => String -> a
panic String
"importSuggestions: dead code"


  -- What import statements provide "Mod" at all
  -- or, if this is an unqualified name, are not qualified imports
  interesting_imports :: [(Module, ImportedModsVal)]
interesting_imports = [ (Module
mod, ImportedModsVal
imp)
    | (Module
mod, [ImportedBy]
mod_imports) <- Map Module [ImportedBy] -> [(Module, [ImportedBy])]
forall k a. Map k a -> [(k, a)]
M.toList (ImportAvails -> Map Module [ImportedBy]
imp_mods ImportAvails
imports)
    , Just ImportedModsVal
imp <- Maybe ImportedModsVal -> [Maybe ImportedModsVal]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ImportedModsVal -> [Maybe ImportedModsVal])
-> Maybe ImportedModsVal -> [Maybe ImportedModsVal]
forall a b. (a -> b) -> a -> b
$ [ImportedModsVal] -> Maybe ImportedModsVal
pick ([ImportedBy] -> [ImportedModsVal]
importedByUser [ImportedBy]
mod_imports)
    ]

  -- We want to keep only one for each original module; preferably one with an
  -- explicit import list (for no particularly good reason)
  pick :: [ImportedModsVal] -> Maybe ImportedModsVal
  pick :: [ImportedModsVal] -> Maybe ImportedModsVal
pick = [ImportedModsVal] -> Maybe ImportedModsVal
forall a. [a] -> Maybe a
listToMaybe ([ImportedModsVal] -> Maybe ImportedModsVal)
-> ([ImportedModsVal] -> [ImportedModsVal])
-> [ImportedModsVal]
-> Maybe ImportedModsVal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ImportedModsVal -> ImportedModsVal -> Ordering)
-> [ImportedModsVal] -> [ImportedModsVal]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ImportedModsVal -> ImportedModsVal -> Ordering
cmp ([ImportedModsVal] -> [ImportedModsVal])
-> ([ImportedModsVal] -> [ImportedModsVal])
-> [ImportedModsVal]
-> [ImportedModsVal]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ImportedModsVal -> Bool) -> [ImportedModsVal] -> [ImportedModsVal]
forall a. (a -> Bool) -> [a] -> [a]
filter ImportedModsVal -> Bool
select
    where select :: ImportedModsVal -> Bool
select ImportedModsVal
imv = case Maybe ModuleName
mod_name of Just ModuleName
name -> ImportedModsVal -> ModuleName
imv_name ImportedModsVal
imv ModuleName -> ModuleName -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleName
name
                                        Maybe ModuleName
Nothing   -> Bool -> Bool
not (ImportedModsVal -> Bool
imv_qualified ImportedModsVal
imv)
          cmp :: ImportedModsVal -> ImportedModsVal -> Ordering
cmp = (Bool -> Bool -> Ordering)
-> (ImportedModsVal -> Bool)
-> ImportedModsVal
-> ImportedModsVal
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on Bool -> Bool -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ImportedModsVal -> Bool
imv_is_hiding (ImportedModsVal -> ImportedModsVal -> Ordering)
-> (ImportedModsVal -> ImportedModsVal -> Ordering)
-> ImportedModsVal
-> ImportedModsVal
-> Ordering
forall a. Semigroup a => a -> a -> a
S.<> (SrcSpan -> SrcSpan -> Ordering)
-> (ImportedModsVal -> SrcSpan)
-> ImportedModsVal
-> ImportedModsVal
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on SrcSpan -> SrcSpan -> Ordering
SrcLoc.leftmost_smallest ImportedModsVal -> SrcSpan
imv_span

  -- Which of these would export a 'foo'
  -- (all of these are restricted imports, because if they were not, we
  -- wouldn't have an out-of-scope error in the first place)
  helpful_imports :: [(Module, ImportedModsVal)]
helpful_imports = ((Module, ImportedModsVal) -> Bool)
-> [(Module, ImportedModsVal)] -> [(Module, ImportedModsVal)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Module, ImportedModsVal) -> Bool
helpful [(Module, ImportedModsVal)]
interesting_imports
    where helpful :: (Module, ImportedModsVal) -> Bool
helpful (Module
_,ImportedModsVal
imv)
            = (GlobalRdrElt -> Bool) -> [GlobalRdrElt] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (LookingFor -> GlobalRdrElt -> Bool
isGreOk LookingFor
looking_for) ([GlobalRdrElt] -> Bool) -> [GlobalRdrElt] -> Bool
forall a b. (a -> b) -> a -> b
$
              GlobalRdrEnv -> LookupGRE GREInfo -> [GlobalRdrElt]
forall info.
GlobalRdrEnvX info -> LookupGRE info -> [GlobalRdrEltX info]
lookupGRE (ImportedModsVal -> GlobalRdrEnv
imv_all_exports ImportedModsVal
imv)
                (OccName -> WhichGREs GREInfo -> LookupGRE GREInfo
forall info. OccName -> WhichGREs info -> LookupGRE info
LookupOccName OccName
occ_name (WhichGREs GREInfo -> LookupGRE GREInfo)
-> WhichGREs GREInfo -> LookupGRE GREInfo
forall a b. (a -> b) -> a -> b
$ FieldsOrSelectors -> WhichGREs GREInfo
RelevantGREsFOS FieldsOrSelectors
WantNormal)

  -- Which of these do that because of an explicit hiding list resp. an
  -- explicit import list
  ([(Module, ImportedModsVal)]
helpful_imports_hiding, [(Module, ImportedModsVal)]
helpful_imports_non_hiding)
    = ((Module, ImportedModsVal) -> Bool)
-> [(Module, ImportedModsVal)]
-> ([(Module, ImportedModsVal)], [(Module, ImportedModsVal)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (ImportedModsVal -> Bool
imv_is_hiding (ImportedModsVal -> Bool)
-> ((Module, ImportedModsVal) -> ImportedModsVal)
-> (Module, ImportedModsVal)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Module, ImportedModsVal) -> ImportedModsVal
forall a b. (a, b) -> b
snd) [(Module, ImportedModsVal)]
helpful_imports

  -- See Note [When to show/hide the module-not-imported line]
  show_not_imported_line :: ModuleName -> Bool                    -- #15611
  show_not_imported_line :: ModuleName -> Bool
show_not_imported_line ModuleName
modnam
      | ModuleName
modnam ModuleName -> [ModuleName] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ModuleName]
glob_mods               = Bool
False    -- #14225     -- 1
      | Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName Module
currMod ModuleName -> ModuleName -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleName
modnam          = Bool
False                  -- 2.1
      | ModuleName -> [Unique] -> Bool
forall {a}. Uniquable a => a -> [Unique] -> Bool
is_last_loaded_mod ModuleName
modnam [Unique]
hpt_uniques = Bool
False                  -- 2.2
      | Bool
otherwise                             = Bool
True
    where
      hpt_uniques :: [Unique]
hpt_uniques = ((Unique, HomeModInfo) -> Unique)
-> [(Unique, HomeModInfo)] -> [Unique]
forall a b. (a -> b) -> [a] -> [b]
map (Unique, HomeModInfo) -> Unique
forall a b. (a, b) -> a
fst (HomePackageTable -> [(Unique, HomeModInfo)]
forall {k} (key :: k) elt. UniqDFM key elt -> [(Unique, elt)]
udfmToList HomePackageTable
hpt)
      is_last_loaded_mod :: a -> [Unique] -> Bool
is_last_loaded_mod a
modnam [Unique]
uniqs = [Unique] -> Maybe Unique
forall a. [a] -> Maybe a
lastMaybe [Unique]
uniqs Maybe Unique -> Maybe Unique -> Bool
forall a. Eq a => a -> a -> Bool
== Unique -> Maybe Unique
forall a. a -> Maybe a
Just (a -> Unique
forall a. Uniquable a => a -> Unique
getUnique a
modnam)
      glob_mods :: [ModuleName]
glob_mods = [ModuleName] -> [ModuleName]
forall a. Eq a => [a] -> [a]
nub [ ModuleName
mod
                      | GlobalRdrElt
gre <- GlobalRdrEnv -> [GlobalRdrElt]
forall info. GlobalRdrEnvX info -> [GlobalRdrEltX info]
globalRdrEnvElts GlobalRdrEnv
global_env
                      , (ModuleName
mod, HowInScope
_) <- GlobalRdrElt -> [(ModuleName, HowInScope)]
qualsInScope GlobalRdrElt
gre
                      ]

extensionSuggestions :: RdrName -> [GhcHint]
extensionSuggestions :: RdrName -> [GhcHint]
extensionSuggestions RdrName
rdrName
  | RdrName
rdrName RdrName -> RdrName -> Bool
forall a. Eq a => a -> a -> Bool
== NameSpace -> FastString -> RdrName
mkUnqual NameSpace
varName (String -> FastString
fsLit String
"mdo") Bool -> Bool -> Bool
||
    RdrName
rdrName RdrName -> RdrName -> Bool
forall a. Eq a => a -> a -> Bool
== NameSpace -> FastString -> RdrName
mkUnqual NameSpace
varName (String -> FastString
fsLit String
"rec")
  = [LanguageExtensionHint -> GhcHint
SuggestExtension (LanguageExtensionHint -> GhcHint)
-> LanguageExtensionHint -> GhcHint
forall a b. (a -> b) -> a -> b
$ SDoc -> Extension -> LanguageExtensionHint
SuggestSingleExtension SDoc
forall doc. IsOutput doc => doc
empty Extension
LangExt.RecursiveDo]
  | Bool
otherwise
  = []

qualsInScope :: GlobalRdrElt -> [(ModuleName, HowInScope)]
-- Ones for which the qualified version is in scope
qualsInScope :: GlobalRdrElt -> [(ModuleName, HowInScope)]
qualsInScope gre :: GlobalRdrElt
gre@GRE { gre_lcl :: forall info. GlobalRdrEltX info -> Bool
gre_lcl = Bool
lcl, gre_imp :: forall info. GlobalRdrEltX info -> Bag ImportSpec
gre_imp = Bag ImportSpec
is }
      | Bool
lcl = case GlobalRdrElt -> Maybe Module
forall info. GlobalRdrEltX info -> Maybe Module
greDefinitionModule GlobalRdrElt
gre of
                Maybe Module
Nothing -> []
                Just Module
m  -> [(Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName Module
m, SrcSpan -> HowInScope
LocallyBoundAt (GlobalRdrElt -> SrcSpan
forall info. GlobalRdrEltX info -> SrcSpan
greDefinitionSrcSpan GlobalRdrElt
gre))]
      | Bool
otherwise = [ (ImpDeclSpec -> ModuleName
is_as ImpDeclSpec
ispec, ImpDeclSpec -> HowInScope
ImportedBy ImpDeclSpec
ispec)
                    | ImportSpec
i <- Bag ImportSpec -> [ImportSpec]
forall a. Bag a -> [a]
bagToList Bag ImportSpec
is, let ispec :: ImpDeclSpec
ispec = ImportSpec -> ImpDeclSpec
is_decl ImportSpec
i ]

isGreOk :: LookingFor -> GlobalRdrElt -> Bool
isGreOk :: LookingFor -> GlobalRdrElt -> Bool
isGreOk (LF WhatLooking
what_look WhereLooking
where_look) GlobalRdrElt
gre = Bool
what_ok Bool -> Bool -> Bool
&& Bool
where_ok
  where
    -- when looking for record fields, what_ok checks whether the GRE is a
    -- record field. Otherwise, it checks whether the GRE is a record field
    -- defined in a module with -XNoFieldSelectors - it wouldn't be a useful
    -- suggestion in that case.
    what_ok :: Bool
what_ok  = case WhatLooking
what_look of
                 WhatLooking
WL_RecField -> GlobalRdrElt -> Bool
forall info. GlobalRdrEltX info -> Bool
isRecFldGRE GlobalRdrElt
gre
                 WhatLooking
_           -> Bool -> Bool
not (GlobalRdrElt -> Bool
isNoFieldSelectorGRE GlobalRdrElt
gre)

    where_ok :: Bool
where_ok = case WhereLooking
where_look of
                 WhereLooking
WL_LocalTop  -> GlobalRdrElt -> Bool
forall info. GlobalRdrEltX info -> Bool
isLocalGRE GlobalRdrElt
gre
                 WhereLooking
WL_LocalOnly -> Bool
False
                 WhereLooking
_            -> Bool
True

-- see Note [Related name spaces]
nameSpacesRelated :: DynFlags    -- ^ to find out whether -XDataKinds is enabled
                  -> WhatLooking -- ^ What kind of name are we looking for
                  -> NameSpace   -- ^ Name space of the original name
                  -> NameSpace   -- ^ Name space of a name that might have been meant
                  -> Bool
nameSpacesRelated :: DynFlags -> WhatLooking -> NameSpace -> NameSpace -> Bool
nameSpacesRelated DynFlags
dflags WhatLooking
what_looking NameSpace
ns NameSpace
ns'
  | NameSpace
ns NameSpace -> NameSpace -> Bool
forall a. Eq a => a -> a -> Bool
== NameSpace
ns'
  = Bool
True
  | Bool
otherwise
  = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or [ NameSpace -> Bool
other_ns NameSpace
ns'
       | (NameSpace -> Bool
orig_ns, [(NameSpace -> Bool, [WhatLooking])]
others) <- [(NameSpace -> Bool, [(NameSpace -> Bool, [WhatLooking])])]
other_namespaces
       , NameSpace -> Bool
orig_ns NameSpace
ns
       , (NameSpace -> Bool
other_ns, [WhatLooking]
wls) <- [(NameSpace -> Bool, [WhatLooking])]
others
       , WhatLooking
what_looking WhatLooking -> [WhatLooking] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` WhatLooking
WL_Anything WhatLooking -> [WhatLooking] -> [WhatLooking]
forall a. a -> [a] -> [a]
: [WhatLooking]
wls
       ]
  where
    -- explanation:
    -- [(orig_ns, [(other_ns, what_looking_possibilities)])]
    -- A particular other_ns is related if the original namespace is orig_ns
    -- and what_looking is either WL_Anything or is one of
    -- what_looking_possibilities
    other_namespaces :: [(NameSpace -> Bool, [(NameSpace -> Bool, [WhatLooking])])]
other_namespaces =
      [ (NameSpace -> Bool
isVarNameSpace     , [(NameSpace -> Bool
isFieldNameSpace  , [WhatLooking
WL_RecField])
                              ,(NameSpace -> Bool
isDataConNameSpace, [WhatLooking
WL_Constructor])])
      , (NameSpace -> Bool
isDataConNameSpace , [(NameSpace -> Bool
isVarNameSpace    , [WhatLooking
WL_RecField])])
      , (NameSpace -> Bool
isTvNameSpace      , (NameSpace -> Bool
isTcClsNameSpace   , [WhatLooking
WL_Constructor])
                              (NameSpace -> Bool, [WhatLooking])
-> [(NameSpace -> Bool, [WhatLooking])]
-> [(NameSpace -> Bool, [WhatLooking])]
forall a. a -> [a] -> [a]
: [(NameSpace -> Bool, [WhatLooking])]
promoted_datacons)
      , (NameSpace -> Bool
isTcClsNameSpace   , (NameSpace -> Bool
isTvNameSpace     , [])
                              (NameSpace -> Bool, [WhatLooking])
-> [(NameSpace -> Bool, [WhatLooking])]
-> [(NameSpace -> Bool, [WhatLooking])]
forall a. a -> [a] -> [a]
: [(NameSpace -> Bool, [WhatLooking])]
promoted_datacons)
      ]
    -- If -XDataKinds is enabled, the data constructor name space is also
    -- related to the type-level name spaces
    data_kinds :: Bool
data_kinds = Extension -> DynFlags -> Bool
xopt Extension
LangExt.DataKinds DynFlags
dflags
    promoted_datacons :: [(NameSpace -> Bool, [WhatLooking])]
promoted_datacons = [(NameSpace -> Bool
isDataConNameSpace, [WhatLooking
WL_Constructor]) | Bool
data_kinds]

{- Note [Related name spaces]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Name spaces are related if there is a chance to mean the one when one writes
the other, i.e. variables <-> data constructors and type variables <-> type
constructors.

In most contexts, this mistake can happen in both directions. Not so in
patterns:

When a user writes
        foo (just a) = ...
It is possible that they meant to use `Just` instead. However, when they write
        foo (Map a) = ...
It is unlikely that they mean to use `map`, since variables cannot be used here.

Similarly, when we look for record fields, data constructors are not in a
related namespace.

Furthermore, with -XDataKinds, the data constructor name space is related to
the type variable and type constructor name spaces.

Note [When to show/hide the module-not-imported line]           -- #15611
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For the error message:
    Not in scope X.Y
    Module X does not export Y
    No module named ‘X’ is imported:
there are 2 cases, where we hide the last "no module is imported" line:
1. If the module X has been imported.
2. If the module X is the current module. There are 2 subcases:
   2.1 If the unknown module name is in a input source file,
       then we can use the getModule function to get the current module name.
       (See test T15611a)
   2.2 If the unknown module name has been entered by the user in GHCi,
       then the getModule function returns something like "interactive:Ghci1",
       and we have to check the current module in the last added entry of
       the HomePackageTable. (See test T15611b)
-}