+ returnTc (env, all_things, dfuns, rules)
+ )
+
+
+tcImports :: RecTcEnv
+ -> PersistentCompilerState
+ -> HomeSymbolTable
+ -> Module
+ -> [RenamedTyClDecl]
+ -> [RenamedInstDecl]
+ -> [RenamedRuleDecl]
+ -> TcM (TcEnv, PersistentCompilerState)
+
+-- tcImports is a slight mis-nomer.
+-- It deals with everything that could be an import:
+-- type and class decls (some source, some imported)
+-- interface signatures (checked lazily)
+-- instance decls (some source, some imported)
+-- rule decls (all imported)
+-- These can occur in source code too, of course
+--
+-- tcImports is only called when processing source code,
+-- so that any interface-file declarations are for other modules, not this one
+
+tcImports unf_env pcs hst this_mod
+ tycl_decls inst_decls rule_decls
+ -- (unf_env :: RecTcEnv) is used for type-checking interface pragmas
+ -- which is done lazily [ie failure just drops the pragma
+ -- without having any global-failure effect].
+ --
+ -- unf_env is also used to get the pragama info
+ -- for imported dfuns and default methods
+
+ = checkNoErrsTc $
+ -- tcImports recovers internally, but if anything gave rise to
+ -- an error we'd better stop now, to avoid a cascade
+
+ traceTc (text "Tc1") `thenNF_Tc_`
+ tcTyAndClassDecls unf_env this_mod tycl_decls `thenTc` \ tycl_things ->
+ tcExtendGlobalEnv tycl_things $
+
+ -- Interface type signatures
+ -- We tie a knot so that the Ids read out of interfaces are in scope
+ -- when we read their pragmas.
+ -- What we rely on is that pragmas are typechecked lazily; if
+ -- any type errors are found (ie there's an inconsistency)
+ -- we silently discard the pragma
+ traceTc (text "Tc2") `thenNF_Tc_`
+ tcInterfaceSigs unf_env this_mod tycl_decls `thenTc` \ sig_ids ->
+ tcExtendGlobalValEnv sig_ids $
+
+ -- Typecheck the instance decls, includes deriving
+ -- Note that imported dictionary functions are already
+ -- in scope from the preceding tcInterfaceSigs
+ traceTc (text "Tc3") `thenNF_Tc_`
+ tcIfaceInstDecls1 inst_decls `thenTc` \ dfuns ->
+ tcIfaceRules rule_decls `thenNF_Tc` \ rules ->
+
+ addInstDFuns (pcs_insts pcs) dfuns `thenNF_Tc` \ new_pcs_insts ->
+ tcGetEnv `thenTc` \ unf_env ->
+ let
+ -- sometimes we're compiling in the context of a package module
+ -- (on the GHCi command line, for example). In this case, we
+ -- want to treat everything we pulled in as an imported thing.
+ imported_things = map AnId sig_ids ++ -- All imported
+ filter (not . isLocalThing this_mod) tycl_things
+
+ new_pte :: PackageTypeEnv
+ new_pte = extendTypeEnvList (pcs_PTE pcs) imported_things
+
+ new_pcs_rules = addIfaceRules (pcs_rules pcs) rules
+
+ new_pcs :: PersistentCompilerState
+ new_pcs = pcs { pcs_PTE = new_pte,
+ pcs_insts = new_pcs_insts,
+ pcs_rules = new_pcs_rules
+ }
+ in
+ returnTc (unf_env, new_pcs)
+
+isSourceRuleDecl :: Module -> RenamedRuleDecl -> Bool
+-- This is a bit gruesome.
+-- Usually, HsRules come only from source files; IfaceRules only from interface files
+-- But built-in rules appear as an IfaceRuleOut... and when compiling
+-- the source file for that built-in rule, we want to treat it as a source
+-- rule, so it gets put with the other rules for that module.
+isSourceRuleDecl this_mod (HsRule _ _ _ _ _ _) = True
+isSourceRuleDecl this_mod (IfaceRule _ _ _ n _ _ _) = False
+isSourceRuleDecl this_mod (IfaceRuleOut name _) = isLocalThing this_mod name
+
+addIfaceRules rule_base rules
+ = foldl add_rule rule_base rules
+ where
+ add_rule rule_base (IfaceRuleOut id rule) = extendRuleBase rule_base (id, rule)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Checking the type of main}
+%* *
+%************************************************************************
+
+We must check that in module Main,
+ a) Main.main is in scope
+ b) Main.main :: forall a1...an. IO t, for some type t
+
+Then we build
+ $main = PrelTopHandler.runMain Main.main
+
+The function
+ PrelTopHandler :: IO a -> IO ()
+catches the top level exceptions.
+It accepts a Main.main of any type (IO a).
+
+\begin{code}
+tcCheckMain :: Maybe Name -> TcM (TypecheckedMonoBinds, LIE)
+tcCheckMain Nothing = returnTc (EmptyMonoBinds, emptyLIE)
+
+tcCheckMain (Just main_name)
+ = tcLookupId main_name `thenNF_Tc` \ main_id ->
+ -- If it is not Nothing, it should be in the env
+ tcAddSrcLoc (getSrcLoc main_id) $
+ tcAddErrCtxt mainCtxt $
+ newTyVarTy liftedTypeKind `thenNF_Tc` \ ty ->
+ tcMonoExpr rhs ty `thenTc` \ (main_expr, lie) ->
+ zonkTcType ty `thenNF_Tc` \ ty ->
+ ASSERT( is_io_unit ty )
+ let
+ dollar_main_id = setIdLocalExported (mkLocalId dollarMainName ty)
+ in
+ returnTc (VarMonoBind dollar_main_id main_expr, lie)
+ where
+ rhs = HsApp (HsVar runMainName) (HsVar main_name)
+
+is_io_unit :: Type -> Bool -- True for IO ()
+is_io_unit tau = case tcSplitTyConApp_maybe tau of
+ Just (tc, [arg]) -> getName tc == ioTyConName && isUnitTy arg
+ other -> False
+
+mainCtxt = ptext SLIT("When checking the type of 'main'")