X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcModule.lhs;h=33dd1c82585a617419738db3f9d51581fbf23cb4;hb=1bdff315ddd01f82ab7811d0612a98f56d6248d8;hp=091ce48d7f582c1edf574bd0cfb4e420d50c4fa7;hpb=9d4c03805bafb6b1e1d47306b6a6c591c998e517;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcModule.lhs b/ghc/compiler/typecheck/TcModule.lhs index 091ce48..33dd1c8 100644 --- a/ghc/compiler/typecheck/TcModule.lhs +++ b/ghc/compiler/typecheck/TcModule.lhs @@ -10,56 +10,73 @@ module TcModule ( typecheckModule, SYN_IE(TcResults), SYN_IE(TcResultBinds), - SYN_IE(TcIfaceInfo), SYN_IE(TcSpecialiseRequests), SYN_IE(TcDDumpDeriv) ) where IMP_Ubiq(){-uitous-} -import HsSyn ( HsModule(..), HsBinds(..), Bind, HsExpr, - TyDecl, SpecDataSig, ClassDecl, InstDecl, +import HsSyn ( HsDecl(..), HsModule(..), HsBinds(..), HsExpr, MonoBinds, + TyDecl, SpecDataSig, ClassDecl, InstDecl, IfaceSig, SpecInstSig, DefaultDecl, Sig, Fake, InPat, + SYN_IE(RecFlag), nonRecursive, FixityDecl, IE, ImportDecl ) import RnHsSyn ( SYN_IE(RenamedHsModule), RenamedFixityDecl(..) ) import TcHsSyn ( SYN_IE(TypecheckedHsBinds), SYN_IE(TypecheckedHsExpr), - TcIdOcc(..), zonkBinds, zonkDictBinds ) + SYN_IE(TypecheckedDictBinds), + TcIdOcc(..), zonkBinds ) -import TcMonad hiding ( rnMtoTcM ) +import TcMonad import Inst ( Inst, plusLIE ) import TcBinds ( tcBindsAndThen ) import TcClassDcl ( tcClassDecls2 ) import TcDefaults ( tcDefaults ) import TcEnv ( tcExtendGlobalValEnv, getEnv_LocalIds, - getEnv_TyCons, getEnv_Classes, - tcLookupLocalValueByKey, tcLookupTyConByKey ) + getEnv_TyCons, getEnv_Classes, tcLookupLocalValue, + tcLookupLocalValueByKey, tcLookupTyCon, + tcLookupGlobalValueByKeyMaybe ) +import SpecEnv ( SpecEnv ) +import TcExpr ( tcId ) import TcIfaceSig ( tcInterfaceSigs ) import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) import TcInstUtil ( buildInstanceEnvs, InstInfo ) import TcSimplify ( tcSimplifyTop ) import TcTyClsDecls ( tcTyAndClassDecls1 ) import TcTyDecls ( mkDataBinds ) +import TcType ( SYN_IE(TcType), tcInstType ) +import TcKind ( TcKind ) +import RnMonad ( RnNameSupply(..) ) import Bag ( listToBag ) -import Class ( GenClass, classSelIds ) import ErrUtils ( SYN_IE(Warning), SYN_IE(Error) ) -import Id ( idType, isMethodSelId, isTopLevId, GenId, SYN_IE(IdEnv), nullIdEnv ) -import Maybes ( catMaybes ) -import Name ( isLocallyDefined ) +import Id ( idType, GenId, SYN_IE(IdEnv), nullIdEnv ) +import Maybes ( catMaybes, MaybeErr ) +import Name ( Name, isLocallyDefined, pprModule ) import Pretty -import RnUtils ( SYN_IE(RnEnv) ) -import TyCon ( TyCon ) -import Type ( applyTyCon ) -import TysWiredIn ( unitTy, mkPrimIoTy ) -import TyVar ( SYN_IE(TyVarEnv), nullTyVarEnv ) +import TyCon ( TyCon, isSynTyCon ) +import Class ( GenClass, SYN_IE(Class), classGlobalIds ) +import Type ( applyTyCon, mkSynTy, SYN_IE(Type) ) +import PprType ( GenType, GenTyVar ) +import PprStyle ( PprStyle ) +import TysWiredIn ( unitTy ) +import PrelMods ( gHC_MAIN, mAIN ) +import PrelInfo ( main_NAME, mainPrimIO_NAME, ioTyCon_NAME, primIoTyCon_NAME ) +import TyVar ( GenTyVar, SYN_IE(TyVarEnv), nullTyVarEnv ) import Unify ( unifyTauTy ) import UniqFM ( lookupUFM_Directly, lookupWithDefaultUFM_Directly, filterUFM, eltsUFM ) -import Unique ( iOTyConKey, mainIdKey, mainPrimIOIdKey ) +import Unique ( Unique ) +import UniqSupply ( UniqSupply ) import Util +import Bag ( Bag, isEmptyBag ) import FiniteMap ( emptyFM, FiniteMap ) + +#if __GLASGOW_HASKELL__ >= 202 +import Outputable +#endif + tycon_specs = emptyFM \end{code} @@ -68,7 +85,8 @@ Outside-world interface: -- Convenient type synonyms first: type TcResults = (TcResultBinds, - TcIfaceInfo, + [TyCon], [Class], + Bag InstInfo, -- Instance declaration information TcSpecialiseRequests, TcDDumpDeriv) @@ -80,22 +98,19 @@ type TcResultBinds -- class default-methods binds TypecheckedHsBinds, -- binds from value decls - [(Id, TypecheckedHsExpr)]) -- constant instance binds - -type TcIfaceInfo -- things for the interface generator - = ([Id], [TyCon], [Class], Bag InstInfo) + TypecheckedHsBinds) -- constant instance binds type TcSpecialiseRequests = FiniteMap TyCon [(Bool, [Maybe Type])] -- source tycon specialisation requests type TcDDumpDeriv - = PprStyle -> Pretty + = PprStyle -> Doc --------------- typecheckModule :: UniqSupply - -> RnEnv -- for renaming derivings + -> RnNameSupply -> RenamedHsModule -> MaybeErr (TcResults, -- if all goes well... @@ -103,31 +118,30 @@ typecheckModule (Bag Error, -- if we had errors... Bag Warning) -typecheckModule us rn_env mod - = initTc us (tcModule rn_env mod) +typecheckModule us rn_name_supply mod + = initTc us (tcModule rn_name_supply mod) \end{code} The internal monster: \begin{code} -tcModule :: RnEnv -- for renaming derivings +tcModule :: RnNameSupply -- for renaming derivings -> RenamedHsModule -- input -> TcM s TcResults -- output -tcModule rn_env - (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 +tcModule rn_name_supply + (HsModule mod_name verion exports imports fixities decls src_loc) + = 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]. + -- trace "tc1" $ + fixTc (\ ~(_, _, _, _, _, _, sig_ids) -> + + -- trace "tc2" $ tcExtendGlobalValEnv sig_ids ( -- The knot for instance information. This isn't used at all @@ -135,26 +149,28 @@ tcModule rn_env 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 -> + -- trace "tcTyAndClassDecls:" $ + tcTyAndClassDecls1 rec_inst_mapper decls `thenTc` \ env -> + -- trace "tc3" $ -- Typecheck the instance decls, includes deriving tcSetEnv env ( - --trace "tcInstDecls:" $ - tcInstDecls1 inst_decls_bag specinst_sigs - mod_name rn_env fixities - ) `thenTc` \ (inst_info, deriv_binds, ddump_deriv) -> + -- trace "tcInstDecls:" $ + tcInstDecls1 decls mod_name rn_name_supply + ) `thenTc` \ (inst_info, deriv_binds, ddump_deriv) -> + -- trace "tc4" $ buildInstanceEnvs inst_info `thenTc` \ inst_mapper -> returnTc (inst_mapper, env, inst_info, deriv_binds, ddump_deriv) ) `thenTc` \ (_, env, inst_info, deriv_binds, ddump_deriv) -> + + -- trace "tc5" $ tcSetEnv env ( -- Default declarations - tcDefaults default_decls `thenTc` \ defaulting_tys -> + tcDefaults decls `thenTc` \ defaulting_tys -> tcSetDefaultTys defaulting_tys ( -- for the iface sigs... -- Create any necessary record selector Ids and their bindings @@ -169,8 +185,9 @@ tcModule rn_env -- a) constructors -- b) record selectors -- c) class op selectors + -- d) default-method ids tcExtendGlobalValEnv data_ids $ - tcExtendGlobalValEnv (concat (map classSelIds classes)) $ + tcExtendGlobalValEnv (concat (map classGlobalIds classes)) $ -- Interface type signatures -- We tie a knot so that the Ids read out of interfaces are in scope @@ -178,34 +195,37 @@ tcModule rn_env -- 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 -> + tcInterfaceSigs decls `thenTc` \ sig_ids -> tcGetEnv `thenNF_Tc` \ env -> + -- trace "tc6" $ returnTc (env, inst_info, data_binds, deriv_binds, ddump_deriv, defaulting_tys, sig_ids) )))) `thenTc` \ (env, inst_info, data_binds, deriv_binds, ddump_deriv, defaulting_tys, _) -> + -- trace "tc7" $ tcSetEnv env ( -- to the end... tcSetDefaultTys defaulting_tys ( -- ditto -- Value declarations next. -- We also typecheck any extra binds that came out of the "deriving" process - --trace "tcBinds:" $ + -- trace "tcBinds:" $ tcBindsAndThen (\ binds1 (binds2, thing) -> (binds1 `ThenBinds` binds2, thing)) - (val_decls `ThenBinds` deriv_binds) + (get_val_decls decls `ThenBinds` deriv_binds) ( -- Second pass over instance declarations, -- to compile the bindings themselves. + -- trace "tc8" $ tcInstDecls2 inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> - tcClassDecls2 cls_decls_bag `thenNF_Tc` \ (lie_clasdecls, cls_binds) -> + tcClassDecls2 decls `thenNF_Tc` \ (lie_clasdecls, cls_binds) -> + tcCheckMainSig mod_name `thenTc_` 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, _) -> + lie_instdecls `plusLIE` lie_clasdecls + ) + ) - checkTopLevelIds mod_name final_env `thenTc_` + `thenTc` \ ((val_binds, (inst_binds, cls_binds, final_env)), lie_alldecls) -> -- Deal with constant or ambiguous InstIds. How could -- there be ambiguous ones? They can only arise if a @@ -213,8 +233,10 @@ tcModule rn_env -- restriction, and no subsequent decl instantiates its -- type. (Usually, ambiguous type variables are resolved -- during the generalisation step.) + -- trace "tc9" $ tcSimplifyTop lie_alldecls `thenTc` \ const_insts -> + -- Backsubstitution. Monomorphic top-level decls may have -- been instantiated by subsequent decls, and the final -- simplification step may have instantiated some @@ -227,7 +249,8 @@ tcModule rn_env -- These bindings ought really to be bundled together in a huge -- recursive group, but HsSyn doesn't have recursion among Binds, only -- among MonoBinds. Sigh again. - zonkDictBinds nullTyVarEnv nullIdEnv const_insts `thenNF_Tc` \ (const_insts', ve1) -> + zonkBinds nullTyVarEnv nullIdEnv (MonoBind const_insts [] nonRecursive) + `thenNF_Tc` \ (const_insts', ve1) -> zonkBinds nullTyVarEnv ve1 val_binds `thenNF_Tc` \ (val_binds', ve2) -> zonkBinds nullTyVarEnv ve2 data_binds `thenNF_Tc` \ (data_binds', _) -> @@ -241,74 +264,68 @@ tcModule rn_env local_tycons = filter isLocallyDefined tycons local_classes = filter isLocallyDefined classes - local_vals = [ v | v <- eltsUFM ve2, isLocallyDefined v && isTopLevId v ] - -- the isTopLevId is doubtful... in -- FINISHED AT LAST returnTc ( (data_binds', cls_binds', inst_binds', val_binds', const_insts'), - -- the next collection is just for mkInterface - (local_vals, local_tycons, local_classes, inst_info), - - tycon_specs, + local_tycons, local_classes, inst_info, tycon_specs, ddump_deriv ))) - where - ty_decls_bag = listToBag ty_decls - cls_decls_bag = listToBag cls_decls - inst_decls_bag = listToBag inst_decls -\end{code} - - -%************************************************************************ -%* * -\subsection{Error checking code} -%* * -%************************************************************************ +get_val_decls decls = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] +\end{code} -checkTopLevelIds checks that Main.main or GHCmain.mainPrimIO has correct type. \begin{code} -checkTopLevelIds :: FAST_STRING -> TcEnv s -> TcM s () - -checkTopLevelIds mod final_env - | mod /= SLIT("Main") && mod /= SLIT("GHCmain") - = returnTc () - - | mod == SLIT("Main") - = tcSetEnv final_env ( - tcLookupLocalValueByKey mainIdKey `thenNF_Tc` \ maybe_main -> - tcLookupTyConByKey iOTyConKey `thenNF_Tc` \ io_tc -> - - case maybe_main of - Just main -> tcAddErrCtxt mainCtxt $ - unifyTauTy (applyTyCon io_tc [unitTy]) - (idType main) - - Nothing -> failTc (mainNoneIdErr "Main" "main") - ) +tcCheckMainSig mod_name + | not is_main && not is_ghc_main + = returnTc () -- A non-main module + + | otherwise + = -- Check that main is defined + tcLookupTyCon tycon_name `thenTc` \ (_,_,tycon) -> + tcLookupLocalValue main_name `thenNF_Tc` \ maybe_main_id -> + case maybe_main_id of { + Nothing -> failTc (noMainErr mod_name main_name); + Just main_id -> + + -- Check that it has the right type (or a more general one) + let + expected_ty | isSynTyCon tycon = mkSynTy tycon [unitTy] + | otherwise = applyTyCon tycon [unitTy] + -- This is bizarre. There ought to be a suitable function in Type.lhs! + in + tcInstType [] expected_ty `thenNF_Tc` \ expected_tau -> + tcId main_name `thenNF_Tc` \ (_, lie, main_tau) -> + tcSetErrCtxt (mainTyCheckCtxt main_name) $ + unifyTauTy expected_tau + main_tau `thenTc_` + checkTc (isEmptyBag lie) (mainTyMisMatch main_name expected_ty (idType main_id)) + } + where + is_main = mod_name == mAIN + is_ghc_main = mod_name == gHC_MAIN - | mod == SLIT("GHCmain") - = tcSetEnv final_env ( - tcLookupLocalValueByKey mainPrimIOIdKey `thenNF_Tc` \ maybe_prim -> - - case maybe_prim of - Just prim -> tcAddErrCtxt primCtxt $ - unifyTauTy (mkPrimIoTy unitTy) - (idType prim) + main_name | is_main = main_NAME + | otherwise = mainPrimIO_NAME - Nothing -> failTc (mainNoneIdErr "GHCmain" "mainPrimIO") - ) + tycon_name | is_main = ioTyCon_NAME + | otherwise = primIoTyCon_NAME -mainCtxt sty - = ppStr "Main.main should have type IO ()" +mainTyCheckCtxt main_name sty + = hsep [ptext SLIT("When checking that"), ppr sty main_name, ptext SLIT("has the required type")] -primCtxt sty - = ppStr "GHCmain.mainPrimIO should have type PrimIO ()" +noMainErr mod_name main_name sty + = hsep [ptext SLIT("Module"), pprModule sty mod_name, + ptext SLIT("must include a definition for"), ppr sty main_name] -mainNoneIdErr mod n sty - = ppCat [ppPStr SLIT("module"), ppStr mod, ppPStr SLIT("does not contain a definition for"), ppStr n] +mainTyMisMatch :: Name -> Type -> TcType s -> Error +mainTyMisMatch main_name expected actual sty + = hang (hsep [ppr sty main_name, ptext SLIT("has the wrong type")]) + 4 (vcat [ + hsep [ptext SLIT("Expected:"), ppr sty expected], + hsep [ptext SLIT("Inferred:"), ppr sty actual] + ]) \end{code}