+filterImports iface decl_spec Nothing all_avails
+ = return (Nothing, all_avails, mkGenericRdrEnv decl_spec all_avails)
+
+filterImports iface decl_spec (Just (want_hiding, import_items)) all_avails
+ = do
+ -- check for errors, convert RdrNames to Names
+ opt_indexedtypes <- doptM Opt_IndexedTypes
+ items1 <- mapM (lookup_lie opt_indexedtypes) import_items
+
+ let -- build the AvailInfo corresponding to each import item.
+ items2 = [ (ie, filterAvailByIE (unLoc ie) av)
+ | (ie,av) <- concat items1 ]
+
+ -- eliminate duplicates
+ avails = nubAvails (map snd items2)
+
+ -- the new import spec, with Names instead of RdrNames
+ imp_spec_out = Just (want_hiding, map fst items2)
+
+ case want_hiding of
+ True ->
+ let
+ keep n = not (n `elemNameSet` availsToNameSet avails)
+ pruned_avails = filterAvails keep all_avails
+ in do
+ traceRn (text "pruned_avails: " <> ppr pruned_avails)
+ return (imp_spec_out, pruned_avails,
+ mkGenericRdrEnv decl_spec pruned_avails)
+
+ False ->
+ let
+ gres = concat [ mkGlobalRdrEltsFromIE decl_spec lie avail
+ | (lie, avail) <- items2 ]
+ in do
+ traceRn (text "imported avails: " <> ppr avails)
+ return (imp_spec_out, avails, mkGlobalRdrEnv gres)
+ where
+ -- This environment is how we map names mentioned in the import
+ -- list to the actual Name they correspond to, and the family
+ -- that the Name belongs to (an AvailInfo).
+ --
+ -- This env will have entries for data constructors too,
+ -- they won't make any difference because naked entities like T
+ -- in an import list map to TcOccs, not VarOccs.
+ occ_env :: OccEnv (Name,AvailInfo)
+ occ_env = mkOccEnv [ (nameOccName n, (n,a))
+ | a <- all_avails, n <- availNames a ]
+
+ lookup_lie :: Bool -> LIE RdrName -> TcRn [(LIE Name, AvailInfo)]
+ lookup_lie opt_indexedtypes (L loc ieRdr)
+ = do
+ stuff <- setSrcSpan loc $
+ case lookup_ie opt_indexedtypes ieRdr of
+ Failed err -> addErr err >> return []
+ Succeeded a -> return a
+ checkDodgyImport stuff
+ return [ (L loc ie, avail) | (ie,avail) <- stuff ]
+ where
+ -- warn when importing T(..) if T was exported absgtractly
+ checkDodgyImport stuff
+ | IEThingAll n <- ieRdr, (_, AvailTC _ [one]):_ <- stuff
+ = ifOptM Opt_WarnDodgyImports (addWarn (dodgyImportWarn n))
+ -- NB. use the RdrName for reporting the warning
+ checkDodgyImport _
+ = return ()
+
+ -- For each import item, we convert its RdrNames to Names,
+ -- and at the same time construct an AvailInfo corresponding
+ -- to what is actually imported by this item.
+ -- Returns Nothing on error.
+ -- We return a list here, because in the case of an import
+ -- item like C, if we are hiding, then C refers to *both* a
+ -- type/class and a data constructor.
+ lookup_ie :: Bool -> IE RdrName -> MaybeErr Message [(IE Name,AvailInfo)]
+ lookup_ie opt_indexedtypes ie
+ = let bad_ie = Failed (badImportItemErr iface decl_spec ie)
+
+ lookup_name rdrName =
+ case lookupOccEnv occ_env (rdrNameOcc rdrName) of
+ Nothing -> bad_ie
+ Just n -> return n
+ in
+ case ie of
+ IEVar n -> do
+ (name,avail) <- lookup_name n
+ return [(IEVar name, avail)]
+
+ IEThingAll tc -> do
+ (name,avail) <- lookup_name tc
+ return [(IEThingAll name, avail)]
+
+ IEThingAbs tc
+ | want_hiding -- hiding ( C )
+ -- Here the 'C' can be a data constructor
+ -- *or* a type/class, or even both
+ -> let tc_name = lookup_name tc
+ dc_name = lookup_name (setRdrNameSpace tc srcDataName)
+ in
+ case catMaybeErr [ tc_name, dc_name ] of
+ [] -> bad_ie
+ names -> return [ (IEThingAbs n, av) | (n,av) <- names ]
+ | otherwise
+ -> do (name,avail) <- lookup_name tc
+ return [(IEThingAbs name, avail)]
+
+ IEThingWith n ns -> do
+ (name,avail) <- lookup_name n
+ case avail of
+ AvailTC nm subnames | nm == name -> do
+ let env = mkOccEnv [ (nameOccName s, s)
+ | s <- subnames ]
+ let mb_children = map (lookupOccEnv env . rdrNameOcc) ns
+ children <-
+ if any isNothing mb_children
+ then bad_ie
+ else return (catMaybes mb_children)
+ -- check for proper import of indexed types
+ when (not opt_indexedtypes && any isTyConName children) $
+ Failed (typeItemErr (head . filter isTyConName
+ $ children )
+ (text "in import list"))
+ return [(IEThingWith name children, avail)]
+ _otherwise -> bad_ie
+
+ _other -> Failed illegalImportItemErr
+ -- could be IEModuleContents, IEGroup, IEDoc, IEDocNamed
+ -- all errors.
+
+catMaybeErr :: [MaybeErr err a] -> [a]
+catMaybeErr ms = [ a | Succeeded a <- ms ]
+\end{code}
+
+%************************************************************************
+%* *
+ Import/Export Utils
+%* *
+%************************************************************************
+
+\begin{code}
+-- | make a 'GlobalRdrEnv' where all the elements point to the same
+-- import declaration (useful for "hiding" imports, or imports with
+-- no details).
+mkGenericRdrEnv decl_spec avails