X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcModule.lhs;h=2789fa86ad99bdedd5428f09bf72278e1089d9df;hb=ab7fb945890d4a6895d83d60d44260772d3160d4;hp=39122d35240606edcaebbe790f073032c8e56a8f;hpb=f9120c200bcf613b58d742802172fb4c08171f0d;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcModule.lhs b/ghc/compiler/typecheck/TcModule.lhs index 39122d3..2789fa8 100644 --- a/ghc/compiler/typecheck/TcModule.lhs +++ b/ghc/compiler/typecheck/TcModule.lhs @@ -1,260 +1,497 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[TcModule]{Typechecking a whole module} \begin{code} -#include "HsVersions.h" - module TcModule ( - tcModule + typecheckModule, typecheckExpr, TcResults(..) ) where -import Ubiq +#include "HsVersions.h" -import HsSyn ( HsModule(..), HsBinds(..), Bind, HsExpr, - TyDecl, SpecDataSig, ClassDecl, InstDecl, - SpecInstSig, DefaultDecl, Sig, Fake, InPat, - FixityDecl, IE, ImportDecl +import CmdLineOpts ( DynFlag(..), DynFlags, opt_PprStyle_Debug ) +import HsSyn ( HsBinds(..), MonoBinds(..), HsDecl(..), HsExpr(..), + isIfaceRuleDecl, nullBinds, andMonoBindList ) -import RnHsSyn ( RenamedHsModule(..), RenamedFixityDecl(..) ) -import TcHsSyn ( TypecheckedHsBinds(..), TypecheckedHsExpr(..), - TcIdOcc(..), zonkBinds, zonkInst, zonkId ) +import HsTypes ( toHsType ) +import PrelNames ( mAIN_Name, mainName, ioTyConName, printName ) +import RnHsSyn ( RenamedHsBinds, RenamedHsDecl, RenamedHsExpr ) +import TcHsSyn ( TypecheckedMonoBinds, TypecheckedHsExpr, + TypecheckedForeignDecl, TypecheckedRuleDecl, + zonkTopBinds, zonkForeignExports, zonkRules, mkHsLet, + zonkExpr + ) + import TcMonad -import Inst ( Inst, plusLIE ) -import TcBinds ( tcBindsAndThen ) +import TcType ( newTyVarTy, zonkTcType, tcInstType ) +import TcUnify ( unifyTauTy ) +import Inst ( plusLIE ) +import VarSet ( varSetElems ) +import TcBinds ( tcTopBinds ) import TcClassDcl ( tcClassDecls2 ) -import TcDefaults ( tcDefaults ) -import TcEnv ( tcExtendGlobalValEnv, getEnv_LocalIds, - getEnv_TyCons, getEnv_Classes, - tcLookupLocalValueByKey, tcLookupTyConByKey ) +import TcDefaults ( tcDefaults, defaultDefaultTys ) +import TcExpr ( tcMonoExpr ) +import TcEnv ( TcEnv, InstInfo, tcExtendGlobalValEnv, tcLookup_maybe, + isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv, + TcTyThing(..), tcLookupTyCon + ) +import TcRules ( tcIfaceRules, tcSourceRules ) +import TcForeign ( tcForeignImports, tcForeignExports ) import TcIfaceSig ( tcInterfaceSigs ) import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) -import TcInstUtil ( buildInstanceEnvs, InstInfo ) -import TcSimplify ( tcSimplifyTop ) -import TcTyClsDecls ( tcTyAndClassDecls1 ) - -import Bag ( listToBag ) -import Class ( GenClass ) -import Id ( GenId, isDataCon, isMethodSelId, idType ) -import Maybes ( catMaybes ) -import Outputable ( isExported, isLocallyDefined ) -import PrelInfo ( unitTy, mkPrimIoTy ) -import Pretty -import RnUtils ( GlobalNameMappers(..), GlobalNameMapper(..) ) -import TyCon ( TyCon ) -import Type ( applyTyCon ) -import Unify ( unifyTauTy ) -import UniqFM ( lookupUFM_Directly, lookupWithDefaultUFM_Directly, - filterUFM, eltsUFM ) -import Unique ( iOTyConKey, mainIdKey, mainPrimIOIdKey ) +import TcSimplify ( tcSimplifyTop, tcSimplifyInfer ) +import TcTyClsDecls ( tcTyAndClassDecls ) + +import CoreUnfold ( unfoldingTemplate, hasUnfolding ) +import Type ( funResultTy, splitForAllTys, mkForAllTys, mkFunTys, + liftedTypeKind, openTypeKind, mkTyConApp, tyVarsOfType, tidyType ) +import ErrUtils ( printErrorsAndWarnings, errorsFound, dumpIfSet_dyn, showPass ) +import Id ( idType, idName, isLocalId, idUnfolding ) +import Module ( Module, isHomeModule, moduleName ) +import Name ( Name, toRdrName, isGlobalName ) +import Name ( nameEnvElts, lookupNameEnv ) +import TyCon ( tyConGenInfo ) import Util - - -import FiniteMap ( emptyFM ) -tycon_specs = emptyFM - - +import BasicTypes ( EP(..), Fixity ) +import Outputable +import HscTypes ( PersistentCompilerState(..), HomeSymbolTable, + PackageTypeEnv, ModIface(..), + TypeEnv, extendTypeEnvList, + TyThing(..), implicitTyThingIds, + mkTypeEnv + ) \end{code} +Outside-world interface: \begin{code} -tcModule :: GlobalNameMappers -- final renamer info for derivings - -> RenamedHsModule -- input - -> TcM s ((TypecheckedHsBinds, -- record selector binds - TypecheckedHsBinds, -- binds from class decls; does NOT - -- include default-methods bindings - TypecheckedHsBinds, -- binds from instance decls; INCLUDES - -- class default-methods binds - TypecheckedHsBinds, -- binds from value decls - - [(Id, TypecheckedHsExpr)]), -- constant instance binds - - ([RenamedFixityDecl], [Id], [TyCon], [Class], Bag InstInfo), - -- things for the interface generator - - ([TyCon], [Class]), - -- environments of info from this module only - - FiniteMap TyCon [(Bool, [Maybe Type])], - -- source tycon specialisation requests - - PprStyle -> Pretty) -- -ddump-deriving info - -tcModule renamer_name_funs - (HsModule mod_name verion exports imports fixities - ty_decls specdata_sigs cls_decls inst_decls specinst_sigs - default_decls val_decls sigs src_loc) - = ASSERT(null imports) - - tcAddSrcLoc src_loc $ -- record where we're starting - - -- Tie the knot for inteface-file value declaration signatures - -- This info is only used inside the knot for type-checking the - -- pragmas, which is done lazily [ie failure just drops the pragma - -- without having any global-failure effect]. - - fixTc (\ ~(_, _, _, _, _, _, sig_ids) -> - tcExtendGlobalValEnv sig_ids ( - - -- The knot for instance information. This isn't used at all - -- till we type-check value declarations - fixTc ( \ ~(rec_inst_mapper, _, _, _, _, _) -> - - -- Type-check the type and class decls - trace "tcTyAndClassDecls:" $ - tcTyAndClassDecls1 rec_inst_mapper ty_decls_bag cls_decls_bag - `thenTc` \ (env, record_binds) -> - - -- Typecheck the instance decls, includes deriving - tcSetEnv env ( - trace "tcInstDecls:" $ - tcInstDecls1 inst_decls_bag specinst_sigs - mod_name renamer_name_funs fixities - ) `thenTc` \ (inst_info, deriv_binds, ddump_deriv) -> - - buildInstanceEnvs inst_info `thenTc` \ inst_mapper -> - - returnTc (inst_mapper, env, record_binds, inst_info, deriv_binds, ddump_deriv) - - ) `thenTc` \ (_, env, record_binds, inst_info, deriv_binds, ddump_deriv) -> - tcSetEnv env ( - - -- Default declarations - tcDefaults default_decls `thenTc` \ defaulting_tys -> - tcSetDefaultTys defaulting_tys ( -- for the iface sigs... - - -- 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 - tcInterfaceSigs sigs `thenTc` \ sig_ids -> - - returnTc (env, inst_info, record_binds, deriv_binds, ddump_deriv, defaulting_tys, sig_ids) - - )))) `thenTc` \ (env, inst_info, record_binds, deriv_binds, ddump_deriv, defaulting_tys, _) -> +-- Convenient type synonyms first: +data TcResults + = TcResults { + -- All these fields have info *just for this module* + tc_env :: TypeEnv, -- The top level TypeEnv + tc_binds :: TypecheckedMonoBinds, -- Bindings + tc_fords :: [TypecheckedForeignDecl], -- Foreign import & exports. + tc_rules :: [TypecheckedRuleDecl] -- Transformation rules + } + +--------------- +typecheckModule + :: DynFlags + -> PersistentCompilerState + -> HomeSymbolTable + -> ModIface -- Iface for this module + -> PrintUnqualified -- For error printing + -> [RenamedHsDecl] + -> IO (Maybe (PersistentCompilerState, TcResults)) + -- The new PCS is Augmented with imported information, + -- (but not stuff from this module) + + +typecheckModule dflags pcs hst mod_iface unqual decls + = do { maybe_tc_result <- typecheck dflags pcs hst unqual $ + tcModule pcs hst get_fixity this_mod decls + ; printTcDump dflags maybe_tc_result + ; return maybe_tc_result } + where + this_mod = mi_module mod_iface + fixity_env = mi_fixities mod_iface + + get_fixity :: Name -> Maybe Fixity + get_fixity nm = lookupNameEnv fixity_env nm + +--------------- +typecheckExpr :: DynFlags + -> Bool -- True <=> wrap in 'print' to get a result of IO type + -> PersistentCompilerState + -> HomeSymbolTable + -> PrintUnqualified -- For error printing + -> Module + -> (RenamedHsExpr, -- The expression itself + [RenamedHsDecl]) -- Plus extra decls it sucked in from interface files + -> IO (Maybe (PersistentCompilerState, TypecheckedHsExpr, TcType)) + +typecheckExpr dflags wrap_io pcs hst unqual this_mod (expr, decls) + = typecheck dflags pcs hst unqual $ + + -- use the default default settings, i.e. [Integer, Double] + tcSetDefaultTys defaultDefaultTys $ + tcImports pcs hst get_fixity this_mod decls `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) -> + ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules ) + + tcSetEnv env $ + tc_expr expr `thenTc` \ (expr', lie, expr_ty) -> + tcSimplifyInfer smpl_doc + (varSetElems (tyVarsOfType expr_ty)) lie `thenTc` \ (qtvs, lie_free, dict_binds, dict_ids) -> + tcSimplifyTop lie_free `thenTc` \ const_binds -> + let all_expr = mkHsLet const_binds $ + TyLam qtvs $ + DictLam dict_ids $ + mkHsLet dict_binds $ + expr' + all_expr_ty = mkForAllTys qtvs (mkFunTys (map idType dict_ids) expr_ty) + in + zonkExpr all_expr `thenNF_Tc` \ zonked_expr -> + zonkTcType all_expr_ty `thenNF_Tc` \ zonked_ty -> + ioToTc (dumpIfSet_dyn dflags + Opt_D_dump_tc "Typechecked" (ppr zonked_expr)) `thenNF_Tc_` + returnTc (new_pcs, zonked_expr, zonked_ty) - tcSetEnv env ( -- to the end... - tcSetDefaultTys defaulting_tys ( -- ditto + where + get_fixity :: Name -> Maybe Fixity + get_fixity n = pprPanic "typecheckExpr" (ppr n) + + smpl_doc = ptext SLIT("main expression") + + -- Typecheck it, wrapping in 'print' if necessary to + -- get a result of type IO t. Returns the result type + -- that is free in the result type + tc_expr e + | wrap_io = tryTc_ (tc_io_expr (HsApp (HsVar printName) e)) -- Recovery case + (tc_io_expr e) -- Main case + | otherwise = newTyVarTy openTypeKind `thenTc` \ ty -> + tcMonoExpr expr ty `thenTc` \ (expr', lie) -> + returnTc (expr', lie, ty) + + where + -- (tc_io_expr e) typechecks 'e' if that gives a result of IO t, + -- or 'print e' otherwise. Either way the result is of type IO t + tc_io_expr e = newTyVarTy openTypeKind `thenTc` \ ty -> + tcLookupTyCon ioTyConName `thenNF_Tc` \ ioTyCon -> + let + res_ty = mkTyConApp ioTyCon [ty] + in + tcMonoExpr expr res_ty `thenTc` \ (expr', lie) -> + returnTc (expr', lie, res_ty) + +--------------- +typecheck :: DynFlags + -> PersistentCompilerState + -> HomeSymbolTable + -> PrintUnqualified -- For error printing + -> TcM r + -> IO (Maybe r) + +typecheck dflags pcs hst unqual thing_inside + = do { showPass dflags "Typechecker"; + ; env <- initTcEnv hst (pcs_PTE pcs) + + ; (maybe_tc_result, errs) <- initTc dflags env thing_inside + + ; printErrorsAndWarnings unqual errs + + ; if errorsFound errs then + return Nothing + else + return maybe_tc_result + } +\end{code} +The internal monster: +\begin{code} +tcModule :: PersistentCompilerState + -> HomeSymbolTable + -> (Name -> Maybe Fixity) + -> Module + -> [RenamedHsDecl] + -> TcM (PersistentCompilerState, TcResults) + +tcModule pcs hst get_fixity this_mod decls + = -- Type-check the type and class decls, and all imported decls + -- tcImports recovers internally, but if anything gave rise to + -- an error we'd better stop now, to avoid a cascade + checkNoErrsTc ( + tcImports pcs hst get_fixity this_mod decls + ) `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) -> + + tcSetEnv env $ + + -- Foreign import declarations next +-- traceTc (text "Tc4") `thenNF_Tc_` + tcForeignImports decls `thenTc` \ (fo_ids, foi_decls) -> + tcExtendGlobalValEnv fo_ids $ + + -- Default declarations + tcDefaults decls `thenTc` \ defaulting_tys -> + tcSetDefaultTys defaulting_tys $ + -- Value declarations next. -- We also typecheck any extra binds that came out of the "deriving" process - trace "tcBinds:" $ - tcBindsAndThen - (\ binds1 (binds2, thing) -> (binds1 `ThenBinds` binds2, thing)) - (val_decls `ThenBinds` deriv_binds) - ( -- Second pass over instance declarations, - -- to compile the bindings themselves. - tcInstDecls2 inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> - tcClassDecls2 cls_decls_bag `thenNF_Tc` \ (lie_clasdecls, cls_binds) -> - tcGetEnv `thenNF_Tc` \ env -> - returnTc ( (EmptyBinds, (inst_binds, cls_binds, env)), - lie_instdecls `plusLIE` lie_clasdecls, - () )) - - `thenTc` \ ((val_binds, (inst_binds, cls_binds, final_env)), lie_alldecls, _) -> - - checkTopLevelIds mod_name final_env `thenTc_` - - -- Deal with constant or ambiguous InstIds. How could - -- there be ambiguous ones? They can only arise if a - -- top-level decl falls under the monomorphism - -- restriction, and no subsequent decl instantiates its - -- type. (Usually, ambiguous type variables are resolved - -- during the generalisation step.) - tcSimplifyTop lie_alldecls `thenTc` \ const_insts -> +-- traceTc (text "Tc5") `thenNF_Tc_` + tcTopBinds (val_binds `ThenBinds` deriv_binds) `thenTc` \ ((val_binds, env), lie_valdecls) -> + tcSetEnv env $ + + -- Foreign export declarations next +-- traceTc (text "Tc6") `thenNF_Tc_` + tcForeignExports decls `thenTc` \ (lie_fodecls, foe_binds, foe_decls) -> + + -- Second pass over class and instance declarations, + -- to compile the bindings themselves. + tcInstDecls2 local_inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> + tcClassDecls2 this_mod tycl_decls `thenNF_Tc` \ (lie_clasdecls, cls_dm_binds) -> + tcSourceRules source_rules `thenNF_Tc` \ (lie_rules, more_local_rules) -> + + -- Deal with constant or ambiguous InstIds. How could + -- there be ambiguous ones? They can only arise if a + -- top-level decl falls under the monomorphism + -- restriction, and no subsequent decl instantiates its + -- type. (Usually, ambiguous type variables are resolved + -- during the generalisation step.) let - localids = getEnv_LocalIds final_env - tycons = getEnv_TyCons final_env - classes = getEnv_Classes final_env - - local_tycons = filter isLocallyDefined tycons - local_classes = filter isLocallyDefined classes + lie_alldecls = lie_valdecls `plusLIE` + lie_instdecls `plusLIE` + lie_clasdecls `plusLIE` + lie_fodecls `plusLIE` + lie_rules + in + tcSimplifyTop lie_alldecls `thenTc` \ const_inst_binds -> - exported_ids = [v | v <- localids, - isExported v && not (isDataCon v) && not (isMethodSelId v)] + -- CHECK THAT main IS DEFINED WITH RIGHT TYPE, IF REQUIRED + tcCheckMain this_mod `thenTc_` + + -- Backsubstitution. This must be done last. + -- Even tcSimplifyTop may do some unification. + let + all_binds = val_binds `AndMonoBinds` + inst_binds `AndMonoBinds` + cls_dm_binds `AndMonoBinds` + const_inst_binds `AndMonoBinds` + foe_binds in - -- Backsubstitution. Monomorphic top-level decls may have - -- been instantiated by subsequent decls, and the final - -- simplification step may have instantiated some - -- ambiguous types. So, sadly, we need to back-substitute - -- over the whole bunch of bindings. - zonkBinds record_binds `thenNF_Tc` \ record_binds' -> - zonkBinds val_binds `thenNF_Tc` \ val_binds' -> - zonkBinds inst_binds `thenNF_Tc` \ inst_binds' -> - zonkBinds cls_binds `thenNF_Tc` \ cls_binds' -> - mapNF_Tc zonkInst const_insts `thenNF_Tc` \ const_insts' -> - mapNF_Tc (zonkId.TcId) exported_ids `thenNF_Tc` \ exported_ids' -> - - -- FINISHED AT LAST - returnTc ( - (record_binds', cls_binds', inst_binds', val_binds', const_insts'), - - -- the next collection is just for mkInterface - (fixities, exported_ids', tycons, classes, inst_info), - - (local_tycons, local_classes), - - tycon_specs, - - ddump_deriv - ))) +-- traceTc (text "Tc9") `thenNF_Tc_` + zonkTopBinds all_binds `thenNF_Tc` \ (all_binds', final_env) -> + tcSetEnv final_env $ + -- zonkTopBinds puts all the top-level Ids into the tcGEnv + zonkForeignExports foe_decls `thenNF_Tc` \ foe_decls' -> + zonkRules more_local_rules `thenNF_Tc` \ more_local_rules' -> + + + let local_things = filter (isLocalThing this_mod) (nameEnvElts (getTcGEnv final_env)) + + -- Create any necessary "implicit" bindings (data constructors etc) + -- Should we create bindings for dictionary constructors? + -- They are always fully applied, and the bindings are just there + -- to support partial applications. But it's easier to let them through. + implicit_binds = andMonoBindList [ CoreMonoBind id (unfoldingTemplate unf) + | id <- implicitTyThingIds local_things + , let unf = idUnfolding id + , hasUnfolding unf + ] + + local_type_env :: TypeEnv + local_type_env = mkTypeEnv local_things + + all_local_rules = local_rules ++ more_local_rules' + in +-- traceTc (text "Tc10") `thenNF_Tc_` + returnTc (new_pcs, + TcResults { tc_env = local_type_env, + tc_binds = implicit_binds `AndMonoBinds` all_binds', + tc_fords = foi_decls ++ foe_decls', + tc_rules = all_local_rules + } + ) where - ty_decls_bag = listToBag ty_decls - cls_decls_bag = listToBag cls_decls - inst_decls_bag = listToBag inst_decls - + tycl_decls = [d | TyClD d <- decls] + val_binds = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] + source_rules = [d | RuleD d <- decls, not (isIfaceRuleDecl d)] \end{code} +\begin{code} +tcImports :: PersistentCompilerState + -> HomeSymbolTable + -> (Name -> Maybe Fixity) + -> Module + -> [RenamedHsDecl] + -> TcM (TcEnv, PersistentCompilerState, + [InstInfo], RenamedHsBinds, [TypecheckedRuleDecl]) + +-- tcImports is a slight mis-nomer. +-- It deals with everythign that could be an import: +-- type and class decls +-- interface signatures +-- instance decls +-- rule decls +-- These can occur in source code too, of course + +tcImports pcs hst get_fixity this_mod decls + = fixTc (\ ~(unf_env, _, _, _, _) -> + -- (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 + +-- traceTc (text "Tc1") `thenNF_Tc_` + tcTyAndClassDecls unf_env tycl_decls `thenTc` \ env -> + tcSetEnv env $ + + -- Typecheck the instance decls, includes deriving +-- traceTc (text "Tc2") `thenNF_Tc_` + tcInstDecls1 (pcs_insts pcs) (pcs_PRS pcs) + hst unf_env get_fixity this_mod + decls `thenTc` \ (new_pcs_insts, inst_env, local_inst_info, deriv_binds) -> + tcSetInstEnv inst_env $ + + -- 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 "Tc3") `thenNF_Tc_` + tcInterfaceSigs unf_env tycl_decls `thenTc` \ sig_ids -> + tcExtendGlobalValEnv sig_ids $ + + + tcIfaceRules (pcs_rules pcs) this_mod iface_rules `thenNF_Tc` \ (new_pcs_rules, local_rules) -> + + tcGetEnv `thenTc` \ unf_env -> + let + all_things = nameEnvElts (getTcGEnv unf_env) + + -- 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 + | isHomeModule this_mod + = filter (not . isLocalThing this_mod) all_things + | otherwise + = all_things + + new_pte :: PackageTypeEnv + new_pte = extendTypeEnvList (pcs_PTE pcs) imported_things + + 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, local_inst_info, deriv_binds, local_rules) + ) + where + tycl_decls = [d | TyClD d <- decls] + iface_rules = [d | RuleD d <- decls, isIfaceRuleDecl d] +\end{code} + %************************************************************************ %* * -\subsection{Error checking code} +\subsection{Checking the type of main} %* * %************************************************************************ +We must check that in module Main, + a) main is defined + b) main :: forall a1...an. IO t, for some type t + +If we have + main = error "Urk" +then the type of main will be + main :: forall a. a +and that should pass the test too. -checkTopLevelIds checks that Main.main or Main.mainPrimIO has correct type. +So we just instantiate the type and unify with IO t, and declare +victory if doing so succeeds. \begin{code} -checkTopLevelIds :: FAST_STRING -> TcEnv s -> TcM s () -checkTopLevelIds mod final_env - | mod /= SLIT("Main") +tcCheckMain :: Module -> TcM () +tcCheckMain this_mod + | not (moduleName this_mod == mAIN_Name ) = returnTc () | otherwise - = tcSetEnv final_env ( - tcLookupLocalValueByKey mainIdKey `thenNF_Tc` \ maybe_main -> - tcLookupLocalValueByKey mainPrimIOIdKey `thenNF_Tc` \ maybe_prim -> - tcLookupTyConByKey iOTyConKey `thenNF_Tc` \ io_tc -> - - case (maybe_main, maybe_prim) of - (Just main, Nothing) -> tcAddErrCtxt mainCtxt $ - unifyTauTy (applyTyCon io_tc [unitTy]) - (idType main) - - (Nothing, Just prim) -> tcAddErrCtxt primCtxt $ - unifyTauTy (mkPrimIoTy unitTy) - (idType prim) - - (Just _ , Just _ ) -> failTc mainBothIdErr - (Nothing, Nothing) -> failTc mainNoneIdErr - ) - -mainCtxt sty - = ppStr "main should have type IO ()" + = -- First unify the main_id with IO t, for any old t + tcLookup_maybe mainName `thenNF_Tc` \ maybe_thing -> + case maybe_thing of + Just (ATcId main_id) -> check_main_ty (idType main_id) + other -> addErrTc noMainErr + where + check_main_ty main_ty + = tcInstType main_ty `thenNF_Tc` \ (tvs, theta, main_tau) -> + newTyVarTy liftedTypeKind `thenNF_Tc` \ arg_ty -> + tcLookupTyCon ioTyConName `thenNF_Tc` \ ioTyCon -> + tcAddErrCtxtM (mainTypeCtxt main_ty) $ + if not (null theta) then + failWithTc empty -- Context has the error message + else + unifyTauTy main_tau (mkTyConApp ioTyCon [arg_ty]) + +mainTypeCtxt main_ty tidy_env + = zonkTcType main_ty `thenNF_Tc` \ main_ty' -> + returnNF_Tc (tidy_env, ptext SLIT("`main' has the illegal type") <+> + quotes (ppr (tidyType tidy_env main_ty'))) + +noMainErr = hsep [ptext SLIT("Module") <+> quotes (ppr mAIN_Name), + ptext SLIT("must include a definition for") <+> quotes (ptext SLIT("main"))] +\end{code} -primCtxt sty - = ppStr "mainPrimIO should have type PrimIO ()" -mainBothIdErr sty - = ppStr "module Main contains definitions for both main and mainPrimIO" +%************************************************************************ +%* * +\subsection{Dumping output} +%* * +%************************************************************************ -mainNoneIdErr sty - = panic "ToDo: sort out mainIdKey" - -- ppStr "module Main does not contain a definition for main (or mainPrimIO)" +\begin{code} +printTcDump dflags Nothing = return () +printTcDump dflags (Just (_, results)) + = do dumpIfSet_dyn dflags Opt_D_dump_types + "Type signatures" (dump_sigs results) + dumpIfSet_dyn dflags Opt_D_dump_tc + "Typechecked" (dump_tc results) + +dump_tc results + = vcat [ppr (tc_binds results), + pp_rules (tc_rules results), + ppr_gen_tycons [tc | ATyCon tc <- nameEnvElts (tc_env results)] + ] + +dump_sigs results -- Print type signatures + = -- Convert to HsType so that we get source-language style printing + -- And sort by RdrName + vcat $ map ppr_sig $ sortLt lt_sig $ + [ (toRdrName id, toHsType (idType id)) + | AnId id <- nameEnvElts (tc_env results), + want_sig id + ] + where + lt_sig (n1,_) (n2,_) = n1 < n2 + ppr_sig (n,t) = ppr n <+> dcolon <+> ppr t + + want_sig id | opt_PprStyle_Debug = True + | otherwise = isLocalId id && isGlobalName (idName id) + -- isLocalId ignores data constructors, records selectors etc + -- The isGlobalName ignores local dictionary and method bindings + -- that the type checker has invented. User-defined things have + -- Global names. + +ppr_gen_tycons tcs = vcat [ptext SLIT("{-# Generic type constructor details"), + vcat (map ppr_gen_tycon tcs), + ptext SLIT("#-}") + ] + +-- x&y are now Id's, not CoreExpr's +ppr_gen_tycon tycon + | Just ep <- tyConGenInfo tycon + = (ppr tycon <> colon) $$ nest 4 (ppr_ep ep) + + | otherwise = ppr tycon <> colon <+> ptext SLIT("Not derivable") + +ppr_ep (EP from to) + = vcat [ ptext SLIT("Rep type:") <+> ppr (funResultTy from_tau), + ptext SLIT("From:") <+> ppr (unfoldingTemplate (idUnfolding from)), + ptext SLIT("To:") <+> ppr (unfoldingTemplate (idUnfolding to)) + ] + where + (_,from_tau) = splitForAllTys (idType from) +pp_rules [] = empty +pp_rules rs = vcat [ptext SLIT("{-# RULES"), + nest 4 (vcat (map ppr rs)), + ptext SLIT("#-}")] \end{code}