X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Fcompiler%2Ftypecheck%2FTcRnDriver.lhs;h=1f270c3cf81ea747b5d8dc550d3058514b166f81;hb=0ee11df0098509d06cf6fc03d1a18429985b6081;hp=89909357cbd7ffb34483932faef1ca1e498978fa;hpb=23f40f0e9be6d4aa5cf9ea31d73f4013f8e7b4bd;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcRnDriver.lhs b/ghc/compiler/typecheck/TcRnDriver.lhs index 8990935..1f270c3 100644 --- a/ghc/compiler/typecheck/TcRnDriver.lhs +++ b/ghc/compiler/typecheck/TcRnDriver.lhs @@ -1,4 +1,4 @@ -% +s% % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[TcModule]{Typechecking a whole module} @@ -21,19 +21,21 @@ import {-# SOURCE #-} TcSplice ( tcSpliceDecls ) #endif import CmdLineOpts ( DynFlag(..), opt_PprStyle_Debug, dopt ) +import Packages ( moduleToPackageConfig, mkPackageId, package, + isHomeModule ) import DriverState ( v_MainModIs, v_MainFunIs ) import HsSyn ( HsModule(..), HsExtCore(..), HsGroup(..), LHsDecl, SpliceDecl(..), HsBind(..), nlHsApp, nlHsVar, pprLHsBinds ) import RdrHsSyn ( findSplice ) -import PrelNames ( runIOName, rootMainName, mAIN_Name, +import PrelNames ( runIOName, rootMainName, mAIN, main_RDR_Unqual ) import RdrName ( RdrName, mkRdrUnqual, emptyGlobalRdrEnv, plusGlobalRdrEnv ) import TcHsSyn ( zonkTopDecls ) import TcExpr ( tcInferRho ) import TcRnMonad -import TcType ( tidyTopType ) +import TcType ( tidyTopType, tcEqType, mkTyVarTys, substTyWith ) import Inst ( showLIE ) import TcBinds ( tcTopBinds ) import TcDefaults ( tcDefaults ) @@ -44,34 +46,36 @@ import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) import TcIface ( tcExtCoreBindings ) import TcSimplify ( tcSimplifyTop ) import TcTyClsDecls ( tcTyAndClassDecls ) -import LoadIface ( loadOrphanModules ) -import RnNames ( importsFromLocalDecls, rnImports, exportsFromAvail, +import LoadIface ( loadOrphanModules, loadHiBootInterface ) +import RnNames ( importsFromLocalDecls, rnImports, exportsFromAvail, reportUnusedNames, reportDeprecations ) import RnEnv ( lookupSrcOcc_maybe ) import RnSource ( rnSrcDecls, rnTyClDecls, checkModDeprec ) import PprCore ( pprIdRules, pprCoreBindings ) import CoreSyn ( IdCoreRule, bindersOfBinds ) +import DataCon ( dataConWrapId ) import ErrUtils ( Messages, mkDumpDoc, showPass ) import Id ( mkExportedLocalId, isLocalId, idName, idType ) import Var ( Var ) -import Module ( mkHomeModule, mkModuleName, moduleName, moduleEnvElts ) +import Module ( mkModule, moduleEnvElts ) import OccName ( mkVarOcc ) import Name ( Name, isExternalName, getSrcLoc, getOccName ) import NameSet -import TyCon ( tyConHasGenerics ) +import TyCon ( tyConHasGenerics, isSynTyCon, getSynTyConDefn, tyConKind ) import SrcLoc ( srcLocSpan, Located(..), noLoc ) import Outputable import HscTypes ( ModGuts(..), HscEnv(..), ExternalPackageState(..), - GhciMode(..), noDependencies, isOneShot, + GhciMode(..), noDependencies, Deprecs( NoDeprecs ), plusDeprecs, - ForeignStubs(NoStubs), TypeEnv, + ForeignStubs(NoStubs), TyThing(..), + TypeEnv, lookupTypeEnv, extendTypeEnvWithIds, typeEnvIds, typeEnvTyCons, emptyFixityEnv ) #ifdef GHCI import HsSyn ( HsStmtContext(..), Stmt(..), HsExpr(..), HsBindGroup(..), LStmt, LHsExpr, LHsType, mkMatchGroup, - collectStmtsBinders, mkSimpleMatch, placeHolderType, + collectStmtsBinders, mkSimpleMatch, nlLetStmt, nlExprStmt, nlBindStmt, nlResultStmt, nlVarPat ) import RdrName ( GlobalRdrEnv, mkGlobalRdrEnv, GlobalRdrElt(..), Provenance(..), ImportSpec(..), @@ -81,7 +85,7 @@ import TcHsSyn ( mkHsLet, zonkTopLExpr, zonkTopBndrs ) import TcHsType ( kcHsType ) import TcExpr ( tcCheckRho ) import TcIface ( loadImportedInsts ) -import TcMType ( zonkTcType ) +import TcMType ( zonkTcType, zonkQuantifiedTyVar ) import TcUnify ( unifyTyConApp ) import TcMatches ( tcStmtsAndThen, TcStmtCtxt(..) ) import TcSimplify ( tcSimplifyInteractive, tcSimplifyInfer ) @@ -97,8 +101,9 @@ import LoadIface ( loadSrcInterface ) import IfaceSyn ( IfaceDecl(..), IfaceClassOp(..), IfaceConDecl(..), IfaceExtName(..), IfaceConDecls(..), IfaceInst(..), tyThingToIfaceDecl, dfunToIfaceInst ) +import IfaceEnv ( lookupOrig ) import RnEnv ( lookupOccRn, dataTcOccs, lookupFixityRn ) -import Id ( Id, isImplicitId, globalIdDetails ) +import Id ( Id, isImplicitId, setIdType, globalIdDetails ) import MkId ( unsafeCoerceId ) import DataCon ( dataConTyCon ) import TyCon ( tyConName ) @@ -107,14 +112,13 @@ import IdInfo ( GlobalIdDetails(..) ) import SrcLoc ( interactiveSrcLoc, unLoc ) import Kind ( Kind ) import Var ( globaliseId ) -import Name ( nameOccName, nameModuleName ) +import Name ( nameOccName, nameModule ) import NameEnv ( delListFromNameEnv ) import PrelNames ( iNTERACTIVE, ioTyConName, printName, monadNames, itName, returnIOName ) -import Module ( ModuleName, lookupModuleEnvByName ) -import HscTypes ( InteractiveContext(..), ExternalPackageState( eps_PTE ), - HomeModInfo(..), typeEnvElts, typeEnvClasses, - TyThing(..), availName, availNames, icPrintUnqual, - ModIface(..), ModDetails(..), Dependencies(..) ) +import Module ( Module, lookupModuleEnv ) +import HscTypes ( InteractiveContext(..), HomeModInfo(..), typeEnvElts, typeEnvClasses, + availNames, availName, ModIface(..), + ModDetails(..), Dependencies(..) ) import BasicTypes ( RecFlag(..), Fixity ) import Bag ( unitBag ) import ListSetOps ( removeDups ) @@ -143,24 +147,28 @@ tcRnModule :: HscEnv -> Located (HsModule RdrName) -> IO (Messages, Maybe TcGblEnv) -tcRnModule hsc_env (L loc (HsModule maybe_mod exports +tcRnModule hsc_env (L loc (HsModule maybe_mod export_ies import_decls local_decls mod_deprec)) = do { showPass (hsc_dflags hsc_env) "Renamer/typechecker" ; let { this_mod = case maybe_mod of - Nothing -> mkHomeModule mAIN_Name + Nothing -> mAIN -- 'module M where' is omitted Just (L _ mod) -> mod } ; -- The normal case initTc hsc_env this_mod $ setSrcSpan loc $ - do { -- Deal with imports; sets tcg_rdr_env, tcg_imports + do { + checkForPackageModule (hsc_dflags hsc_env) this_mod; + + -- Deal with imports; sets tcg_rdr_env, tcg_imports (rdr_env, imports) <- rnImports import_decls ; - -- In one-shot mode, record boot-file info in the EPS - ifM (isOneShot (hsc_mode hsc_env)) $ - updateEps_ (\eps -> eps { eps_is_boot = imp_dep_mods imports }) ; + -- Record boot-file info in the EPS, so that it's + -- visible to loadHiBootInterface in tcRnSrcDecls, + -- and any other incrementally-performed imports + updateEps_ (\eps -> eps { eps_is_boot = imp_dep_mods imports }) ; -- Update the gbl env updGblEnv ( \ gbl -> gbl { tcg_rdr_env = rdr_env, @@ -191,20 +199,7 @@ tcRnModule hsc_env (L loc (HsModule maybe_mod exports reportDeprecations tcg_env ; -- Process the export list - exports <- exportsFromAvail (isJust maybe_mod) exports ; - -{- Jan 04: I don't think this is necessary any more; usage info is derived from tcg_dus - -- Get any supporting decls for the exports that have not already - -- been sucked in for the declarations in the body of the module. - -- (This can happen if something is imported only to be re-exported.) - -- - -- Importing these supporting declarations is required - -- *only* to gether usage information - -- (see comments with MkIface.mkImportInfo for why) - -- We don't need the results, but sucking them in may side-effect - -- the ExternalPackageState, apart from recording usage - mappM (tcLookupGlobal . availName) export_avails ; --} + exports <- exportsFromAvail (isJust maybe_mod) export_ies ; -- Check whether the entire module is deprecated -- This happens only once per module @@ -225,6 +220,22 @@ tcRnModule hsc_env (L loc (HsModule maybe_mod exports tcDump final_env ; return final_env }}}} + +-- This is really a sanity check that the user has given -package-name +-- if necessary. -package-name is only necessary when the package database +-- already contains the current package, because then we can't tell +-- whether a given module is in the current package or not, without knowing +-- the name of the current package. +checkForPackageModule dflags this_mod + | not (isHomeModule dflags this_mod), + Just (pkg,_) <- moduleToPackageConfig dflags this_mod = + let + ppr_pkg = ppr (mkPackageId (package pkg)) + in + addErr (ptext SLIT("Module") <+> quotes (ppr this_mod) <+> + ptext SLIT("is a member of package") <+> ppr_pkg <> char '.' $$ + ptext SLIT("To compile this module, please use -ignore-package") <+> ppr_pkg <> char '.') + | otherwise = return () \end{code} @@ -264,7 +275,7 @@ tcRnExtCore hsc_env (HsExtCore this_mod decls src_binds) -- Typecheck them all together so that -- any mutually recursive types are done right - tcg_env <- checkNoErrs (tcTyAndClassDecls rn_decls) ; + tcg_env <- checkNoErrs (tcTyAndClassDecls [{- no boot names -}] rn_decls) ; -- Make the new type env available to stuff slurped from interface files setGblEnv tcg_env $ do { @@ -321,8 +332,14 @@ tcRnSrcDecls :: [LHsDecl RdrName] -> TcM TcGblEnv -- Returns the variables free in the decls -- Reason: solely to report unused imports and bindings tcRnSrcDecls decls - = do { -- Do all the declarations - (tc_envs, lie) <- getLIE (tc_rn_src_decls decls) ; + = do { -- Load the hi-boot interface for this module, if any + -- We do this now so that the boot_names can be passed + -- to tcTyAndClassDecls, because the boot_names are + -- automatically considered to be loop breakers + boot_names <- loadHiBootInterface ; + + -- Do all the declarations + (tc_envs, lie) <- getLIE (tc_rn_src_decls boot_names decls) ; -- tcSimplifyTop deals with constant or ambiguous InstIds. -- How could there be ambiguous ones? They can only arise if a @@ -348,6 +365,9 @@ tcRnSrcDecls decls let { final_type_env = extendTypeEnvWithIds type_env bind_ids } ; + -- Compre the hi-boot iface (if any) with the real thing + checkHiBootIface final_type_env boot_names ; + -- Make the new type env available to stuff slurped from interface files writeMutVar (tcg_type_env_var tcg_env) final_type_env ; @@ -355,15 +375,15 @@ tcRnSrcDecls decls tcg_binds = binds', tcg_rules = rules', tcg_fords = fords' }) } -tc_rn_src_decls :: [LHsDecl RdrName] -> TcM (TcGblEnv, TcLclEnv) +tc_rn_src_decls :: [Name] -> [LHsDecl RdrName] -> TcM (TcGblEnv, TcLclEnv) -- Loops around dealing with each top level inter-splice group -- in turn, until it's dealt with the entire module -tc_rn_src_decls ds +tc_rn_src_decls boot_names ds = do { let { (first_group, group_tail) = findSplice ds } ; -- If ds is [] we get ([], Nothing) -- Type check the decls up to, but not including, the first splice - tc_envs@(tcg_env,tcl_env) <- tcRnGroup first_group ; + tc_envs@(tcg_env,tcl_env) <- tcRnGroup boot_names first_group ; -- Bale out if errors; for example, error recovery when checking -- the RHS of 'main' can mean that 'main' is not in the envt for @@ -394,11 +414,82 @@ tc_rn_src_decls ds -- Glue them on the front of the remaining decls and loop setGblEnv (tcg_env `addTcgDUs` usesOnly splice_fvs) $ - tc_rn_src_decls (spliced_decls ++ rest_ds) + tc_rn_src_decls boot_names (spliced_decls ++ rest_ds) #endif /* GHCI */ }}} \end{code} +%************************************************************************ +%* * + Comparing the hi-boot interface with the real thing +%* * +%************************************************************************ + +In both one-shot mode and GHCi mode, hi-boot interfaces are demand-loaded +into the External Package Table. Once we've typechecked the body of the +module, we want to compare what we've found (gathered in a TypeEnv) with +the hi-boot stuff in the EPT. We do so here, using the export list of +the hi-boot interface as our checklist. + +\begin{code} +checkHiBootIface :: TypeEnv -> [Name] -> TcM () +-- Compare the hi-boot file for this module (if there is one) +-- with the type environment we've just come up with +-- In the common case where there is no hi-boot file, the list +-- of boot_names is empty. +checkHiBootIface env boot_names + = mapM_ (check_one env) boot_names + +---------------- +check_one local_env name + = do { eps <- getEps + + -- Look up the hi-boot one; + -- it should jolly well be there (else GHC bug) + ; case lookupTypeEnv (eps_PTE eps) name of { + Nothing -> pprPanic "checkHiBootIface" (ppr name) ; + Just boot_thing -> + + -- Look it up in the local type env + -- It should be there, but it's a programmer error if not + case lookupTypeEnv local_env name of + Nothing -> addErrTc (missingBootThing boot_thing) + Just real_thing -> check_thing boot_thing real_thing + } } + +---------------- +check_thing (ATyCon boot_tc) (ATyCon real_tc) + | isSynTyCon boot_tc && isSynTyCon real_tc, + defn1 `tcEqType` substTyWith tvs2 (mkTyVarTys tvs1) defn2 + = return () + + | tyConKind boot_tc == tyConKind real_tc + = return () + where + (tvs1, defn1) = getSynTyConDefn boot_tc + (tvs2, defn2) = getSynTyConDefn boot_tc + +check_thing (AnId boot_id) (AnId real_id) + | idType boot_id `tcEqType` idType real_id + = return () + +check_thing (ADataCon dc1) (ADataCon dc2) + | idType (dataConWrapId dc1) `tcEqType` idType (dataConWrapId dc2) + = return () + + -- Can't declare a class in a hi-boot file + +check_thing boot_thing real_thing -- Default case; failure + = addErrAt (srcLocSpan (getSrcLoc real_thing)) + (bootMisMatch real_thing) + +---------------- +missingBootThing thing + = ppr thing <+> ptext SLIT("is defined in the hi-boot file, but not in the module") +bootMisMatch thing + = ppr thing <+> ptext SLIT("has conflicting definitions in the module and its hi-boot file") +\end{code} + %************************************************************************ %* * @@ -418,15 +509,15 @@ declarations. It expects there to be an incoming TcGblEnv in the monad; it augments it and returns the new TcGblEnv. \begin{code} -tcRnGroup :: HsGroup RdrName -> TcM (TcGblEnv, TcLclEnv) +tcRnGroup :: [Name] -> HsGroup RdrName -> TcM (TcGblEnv, TcLclEnv) -- Returns the variables free in the decls, for unused-binding reporting -tcRnGroup decls +tcRnGroup boot_names decls = do { -- Rename the declarations (tcg_env, rn_decls) <- rnTopSrcDecls decls ; setGblEnv tcg_env $ do { -- Typecheck the declarations - tcTopSrcDecls rn_decls + tcTopSrcDecls boot_names rn_decls }} ------------------------------------------------ @@ -452,8 +543,8 @@ rnTopSrcDecls group }} ------------------------------------------------ -tcTopSrcDecls :: HsGroup Name -> TcM (TcGblEnv, TcLclEnv) -tcTopSrcDecls +tcTopSrcDecls :: [Name] -> HsGroup Name -> TcM (TcGblEnv, TcLclEnv) +tcTopSrcDecls boot_names (HsGroup { hs_tyclds = tycl_decls, hs_instds = inst_decls, hs_fords = foreign_decls, @@ -464,7 +555,7 @@ tcTopSrcDecls -- The latter come in via tycl_decls traceTc (text "Tc2") ; - tcg_env <- checkNoErrs (tcTyAndClassDecls tycl_decls) ; + tcg_env <- checkNoErrs (tcTyAndClassDecls boot_names tycl_decls) ; -- tcTyAndClassDecls recovers internally, but if anything gave rise to -- an error we'd better stop now, to avoid a cascade @@ -541,8 +632,8 @@ checkMain mb_main_mod <- readMutVar v_MainModIs ; mb_main_fn <- readMutVar v_MainFunIs ; let { main_mod = case mb_main_mod of { - Just mod -> mkModuleName mod ; - Nothing -> mAIN_Name } ; + Just mod -> mkModule mod ; + Nothing -> mAIN } ; main_fn = case mb_main_fn of { Just fn -> mkRdrUnqual (mkVarOcc (mkFastString fn)) ; Nothing -> main_RDR_Unqual } } ; @@ -555,12 +646,9 @@ check_main ghci_mode tcg_env main_mod main_fn -- If we are in module Main, check that 'main' is defined. -- It may be imported from another module! -- - -- ToDo: We have to return the main_name separately, because it's a - -- bona fide 'use', and should be recorded as such, but the others - -- aren't -- -- Blimey: a whole page of code to do this... - | mod_name /= main_mod + | mod /= main_mod = return tcg_env | otherwise @@ -585,10 +673,12 @@ check_main ghci_mode tcg_env main_mod main_fn `snocBag` main_bind, tcg_dus = tcg_dus tcg_env `plusDU` usesOnly (unitFV main_name) + -- Record the use of 'main', so that we don't + -- complain about it being defined but not used }) }}} where - mod_name = moduleName (tcg_mod tcg_env) + mod = tcg_mod tcg_env complain_no_main | ghci_mode == Interactive = return () | otherwise = failWithTc noMainMsg @@ -644,12 +734,16 @@ tcRnStmt hsc_env ictxt rdr_stmt (bound_ids, tc_expr) <- tcUserStmt rn_stmt ; traceTc (text "tcs 1") ; - let { -- Make all the bound ids "global" ids, now that - -- they're notionally top-level bindings. This is - -- important: otherwise when we come to compile an expression - -- using these ids later, the byte code generator will consider - -- the occurrences to be free rather than global. - global_ids = map (globaliseId VanillaGlobal) bound_ids ; + let { -- (a) Make all the bound ids "global" ids, now that + -- they're notionally top-level bindings. This is + -- important: otherwise when we come to compile an expression + -- using these ids later, the byte code generator will consider + -- the occurrences to be free rather than global. + -- + -- (b) Tidy their types; this is important, because :info may + -- ask to look at them, and :info expects the things it looks + -- up to have tidy types + global_ids = map globaliseAndTidy bound_ids ; -- Update the interactive context rn_env = ic_rn_local_env ictxt ; @@ -678,8 +772,14 @@ tcRnStmt hsc_env ictxt rdr_stmt returnM (new_ic, bound_names, tc_expr) } -\end{code} +globaliseAndTidy :: Id -> Id +globaliseAndTidy id +-- Give the Id a Global Name, and tidy its type + = setIdType (globaliseId VanillaGlobal id) tidy_type + where + tidy_type = tidyTopType (idType id) +\end{code} Here is the grand plan, implemented in tcUserStmt @@ -823,8 +923,9 @@ tcRnExpr hsc_env ictxt rdr_expr ((tc_expr, res_ty), lie) <- getLIE (tcInferRho rn_expr) ; ((qtvs, _, dict_ids), lie_top) <- getLIE (tcSimplifyInfer smpl_doc (tyVarsOfType res_ty) lie) ; tcSimplifyInteractive lie_top ; + qtvs' <- mappM zonkQuantifiedTyVar qtvs ; - let { all_expr_ty = mkForAllTys qtvs $ + let { all_expr_ty = mkForAllTys qtvs' $ mkFunTys (map idType dict_ids) $ res_ty } ; zonkTcType all_expr_ty @@ -866,7 +967,7 @@ tcRnType hsc_env ictxt rdr_type \begin{code} #ifdef GHCI -mkExportEnv :: HscEnv -> [ModuleName] -- Expose these modules' exports only +mkExportEnv :: HscEnv -> [Module] -- Expose these modules' exports only -> IO GlobalRdrEnv mkExportEnv hsc_env exports = do { mb_envs <- initTcPrintErrors hsc_env iNTERACTIVE $ @@ -877,18 +978,18 @@ mkExportEnv hsc_env exports -- Some error; initTc will have printed it } -getModuleExports :: ModuleName -> TcM GlobalRdrEnv +getModuleExports :: Module -> TcM GlobalRdrEnv getModuleExports mod = do { iface <- load_iface mod ; loadOrphanModules (dep_orphs (mi_deps iface)) -- Load any orphan-module interfaces, -- so their instances are visible - ; avails <- exportsToAvails (mi_exports iface) + ; names <- exportsToAvails (mi_exports iface) ; let { gres = [ GRE { gre_name = name, gre_prov = vanillaProv mod } - | avail <- avails, name <- availNames avail ] } + | name <- nameSetToList names ] } ; returnM (mkGlobalRdrEnv gres) } -vanillaProv :: ModuleName -> Provenance +vanillaProv :: Module -> Provenance -- We're building a GlobalRdrEnv as if the user imported -- all the specified modules into the global interactive module vanillaProv mod = Imported [ImportSpec mod mod False @@ -899,7 +1000,7 @@ vanillaProv mod = Imported [ImportSpec mod mod False getModuleContents :: HscEnv -> InteractiveContext - -> ModuleName -- Module to inspect + -> Module -- Module to inspect -> Bool -- Grab just the exports, or the whole toplev -> IO (Maybe [IfaceDecl]) @@ -910,7 +1011,7 @@ getModuleContents hsc_env ictxt mod exports_only | not exports_only -- We want the whole top-level type env -- so it had better be a home module = do { hpt <- getHpt - ; case lookupModuleEnvByName hpt mod of + ; case lookupModuleEnv hpt mod of Just mod_info -> return (map toIfaceDecl $ filter wantToSee $ typeEnvElts $ @@ -921,13 +1022,14 @@ getModuleContents hsc_env ictxt mod exports_only | otherwise -- Want the exports only = do { iface <- load_iface mod - ; avails <- exportsToAvails (mi_exports iface) - ; mappM get_decl avails + ; mappM get_decl [ (mod,avail) | (mod, avails) <- mi_exports iface + , avail <- avails ] } - get_decl avail - = do { thing <- tcLookupGlobal (availName avail) - ; return (filter_decl (availOccs avail) (toIfaceDecl thing)) } + get_decl (mod, avail) + = do { main_name <- lookupOrig mod (availName avail) + ; thing <- tcLookupGlobal main_name + ; return (filter_decl (availNames avail) (toIfaceDecl thing)) } --------------------- filter_decl occs decl@(IfaceClass {ifSigs = sigs}) @@ -943,8 +1045,6 @@ filter_decl occs decl keep_sig occs (IfaceClassOp occ _ _) = occ `elem` occs keep_con occs con = ifConOcc con `elem` occs -availOccs avail = map nameOccName (availNames avail) - wantToSee (AnId id) = not (isImplicitId id) wantToSee (ADataCon _) = False -- They'll come via their TyCon wantToSee _ = True @@ -1048,7 +1148,7 @@ toIfaceDecl thing emptyNameSet -- Show data cons ext_nm (munge thing) where - ext_nm n = ExtPkg (nameModuleName n) (nameOccName n) + ext_nm n = ExtPkg (nameModule n) (nameOccName n) -- munge transforms a thing to it's "parent" thing munge (ADataCon dc) = ATyCon (dataConTyCon dc)