-importDecl :: Name -> Necessity -> RnMG (Maybe RdrNameHsDecl)
- -- Returns Nothing for a wired-in or already-slurped decl
-
-importDecl name necessity
- = checkSlurped name `thenRn` \ already_slurped ->
- if already_slurped then
- -- traceRn (ppSep [ppStr "Already slurped:", ppr PprDebug name]) `thenRn_`
- returnRn Nothing -- Already dealt with
- else
- if isWiredInName name then
- getWiredInDecl name
- else
- getIfacesRn `thenRn` \ ifaces ->
- let
- Ifaces this_mod _ _ _ _ _ _ _ = ifaces
- (mod,_) = modAndOcc name
- in
- if mod == this_mod then -- Don't bring in decls from
- pprTrace "importDecl wierdness:" (ppr PprDebug name) $
- returnRn Nothing -- the renamed module's own interface file
- --
- else
- getNonWiredInDecl name necessity
+importDecl :: Name -> RnMG ImportDeclResult
+
+data ImportDeclResult
+ = AlreadySlurped
+ | WiredIn
+ | Deferred
+ | HereItIs (Module, RdrNameHsDecl)
+
+importDecl name
+ = getSlurped `thenRn` \ already_slurped ->
+ if name `elemNameSet` already_slurped then
+ returnRn AlreadySlurped -- Already dealt with
+
+ else if isLocallyDefined name then -- Don't bring in decls from
+ -- the renamed module's own interface file
+ addWarnRn (importDeclWarn name) `thenRn_`
+ returnRn AlreadySlurped
+
+ else if isWiredInName name then
+ -- When we find a wired-in name we must load its
+ -- home module so that we find any instance decls therein
+ loadHomeInterface doc name `thenRn_`
+ returnRn WiredIn
+
+ else getNonWiredInDecl name
+ where
+ doc = ptext SLIT("need home module for wired in thing") <+> ppr name
+
+
+{- I don't think this is necessary any more; SLPJ May 00
+ load_home name
+ | name `elemNameSet` source_binders = returnRn ()
+ -- When compiling the prelude, a wired-in thing may
+ -- be defined in this module, in which case we don't
+ -- want to load its home module!
+ -- Using 'isLocallyDefined' doesn't work because some of
+ -- the free variables returned are simply 'listTyCon_Name',
+ -- with a system provenance. We could look them up every time
+ -- but that seems a waste.
+ | otherwise = loadHomeInterface doc name `thenRn_`
+ returnRn ()
+-}
+
+getNonWiredInDecl :: Name -> RnMG ImportDeclResult
+getNonWiredInDecl needed_name
+ = traceRn doc_str `thenRn_`
+ loadHomeInterface doc_str needed_name `thenRn` \ ifaces ->
+ case lookupNameEnv (iDecls ifaces) needed_name of
+
+ Just (version, avail, is_tycon_name, decl@(_, TyClD (TyData DataType _ _ _ _ ncons _ _ _)))
+ -- This case deals with deferred import of algebraic data types
+
+ | not opt_NoPruneTyDecls
+
+ && (opt_IgnoreIfacePragmas || ncons > 1)
+ -- We only defer if imported interface pragmas are ingored
+ -- or if it's not a product type.
+ -- Sole reason: The wrapper for a strict function may need to look
+ -- inside its arg, and hence need to see its arg type's constructors.
+
+ && not (getUnique tycon_name `elem` cCallishTyKeys)
+ -- Never defer ccall types; we have to unbox them,
+ -- and importing them does no harm
+
+ -> -- OK, so we're importing a deferrable data type
+ if needed_name == tycon_name then
+ -- The needed_name is the TyCon of a data type decl
+ -- Record that it's slurped, put it in the deferred set
+ -- and don't return a declaration at all
+ setIfacesRn (recordSlurp (ifaces {iDeferred = iDeferred ifaces
+ `addOneToNameSet` tycon_name})
+ version (AvailTC needed_name [needed_name])) `thenRn_`
+ returnRn Deferred
+ else
+ -- The needed name is a constructor of a data type decl,
+ -- getting a constructor, so remove the TyCon from the deferred set
+ -- (if it's there) and return the full declaration
+ setIfacesRn (recordSlurp (ifaces {iDeferred = iDeferred ifaces
+ `delFromNameSet` tycon_name})
+ version avail) `thenRn_`
+ returnRn (HereItIs decl)
+ where
+ tycon_name = availName avail