%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[TcInstDecls]{Typechecking instance declarations}
\begin{code}
+module TcInstDcls ( tcInstDecls1, tcInstDecls2, tcAddDeclCtxt ) where
+
#include "HsVersions.h"
-module TcInstDcls (
- tcInstDecls1, tcInstDecls2,
- tcSpecInstSigs,
- buildInstanceEnvs, processInstBinds,
- mkInstanceRelatedIds,
- InstInfo(..)
- ) where
-IMPORT_Trace -- ToDo:rm debugging
-import Outputable
-import Pretty
+import CmdLineOpts ( DynFlag(..), dopt )
+
+import HsSyn ( HsDecl(..), InstDecl(..), TyClDecl(..),
+ MonoBinds(..), HsExpr(..), HsLit(..), Sig(..),
+ andMonoBindList, collectMonoBinders, isClassDecl
+ )
+import RnHsSyn ( RenamedHsBinds, RenamedInstDecl, RenamedHsDecl, RenamedMonoBinds,
+ RenamedTyClDecl, RenamedHsType,
+ extractHsTyVars, maybeGenericMatch
+ )
+import TcHsSyn ( TcMonoBinds, mkHsConApp )
+import TcBinds ( tcSpecSigs )
+import TcClassDcl ( tcMethodBind, badMethodErr )
+import TcMonad
+import Inst ( InstOrigin(..),
+ newDicts, newClassDicts,
+ LIE, emptyLIE, plusLIE, plusLIEs )
+import TcDeriv ( tcDeriving )
+import TcEnv ( TcEnv, tcExtendGlobalValEnv,
+ tcExtendTyVarEnvForMeths,
+ tcAddImportedIdInfo, tcInstId, tcLookupClass,
+ InstInfo(..), pprInstInfo, simpleInstInfoTyCon, simpleInstInfoTy,
+ newDFunName, tcExtendTyVarEnv
+ )
+import InstEnv ( InstEnv, extendInstEnv )
+import TcMonoType ( tcTyVars, tcHsSigType, kcHsSigType )
+import TcSimplify ( tcSimplifyAndCheck )
+import TcType ( zonkTcSigTyVars )
+import HscTypes ( HomeSymbolTable, DFunId,
+ ModDetails(..), PackageInstEnv, PersistentRenamerState
+ )
-import TcMonad -- typechecking monad machinery
-import TcMonadFns ( newDicts, newMethod, newLocalWithGivenTy,
- newClassOpLocals, copyTyVars,
- applyTcSubstAndCollectTyVars
+import Bag ( unionManyBags )
+import DataCon ( classDataCon )
+import Class ( Class, DefMeth(..), classBigSig )
+import Var ( idName, idType )
+import Maybes ( maybeToBool )
+import MkId ( mkDictFunId )
+import Generics ( validGenericInstanceType )
+import Module ( Module, foldModuleEnv )
+import Name ( getSrcLoc )
+import NameSet ( emptyNameSet, nameSetToList )
+import PrelInfo ( eRROR_ID )
+import PprType ( pprConstraint, pprPred )
+import TyCon ( TyCon, isSynTyCon )
+import Type ( splitDFunTy, isTyVarTy,
+ splitTyConApp_maybe, splitDictTy,
+ splitForAllTys,
+ tyVarsOfTypes, mkClassPred, mkTyVarTy,
+ getClassTys_maybe
)
-import AbsSyn -- the stuff being typechecked
-import AbsPrel ( pAT_ERROR_ID )
-import AbsUniType
-import BackSubst ( applyTcSubstToBinds )
-import Bag ( emptyBag, unitBag, unionBags, bagToList )
-import CE ( lookupCE, CE(..) )
-import CmdLineOpts ( GlobalSwitch(..) )
-import GenSpecEtc ( checkSigTyVars, SignatureInfo )
-import E ( mkE, getE_CE, getE_TCE, growE_LVE, tvOfE, LVE(..), E )
-import Errors ( dupInstErr, derivingWhenInstanceExistsErr,
- preludeInstanceErr, nonBoxedPrimCCallErr,
- specInstUnspecInstNotFoundErr,
- Error(..), UnifyErrContext(..)
+import Subst ( mkTopTyVarSubst, substClasses )
+import VarSet ( mkVarSet, varSetElems )
+import TysWiredIn ( genericTyCons, isFFIArgumentTy, isFFIResultTy )
+import PrelNames ( cCallableClassKey, cReturnableClassKey, hasKey )
+import Name ( Name )
+import SrcLoc ( SrcLoc )
+import VarSet ( varSetElems )
+import Unique ( Uniquable(..) )
+import BasicTypes ( NewOrData(..), Fixity )
+import ErrUtils ( dumpIfSet_dyn )
+import ListSetOps ( Assoc, emptyAssoc, plusAssoc_C, mapAssoc,
+ assocElts, extendAssoc_C,
+ equivClassesByUniq, minusList
)
-import HsPragmas -- ****** NEED TO SEE CONSTRUCTORS ******
-import Id -- lots of things
-import IdInfo -- ditto
-import Inst ( Inst, InstOrigin(..) )
-import InstEnv
-import Maybes ( catMaybes, mkLookupFun, maybeToBool, Maybe(..) )
-import Name ( getTagFromClassOpName )
-import NameTypes ( fromPrelude )
-import PlainCore ( escErrorMsg )
-import LIE ( nullLIE, mkLIE, unMkLIE, plusLIE, LIE )
-import ListSetOps ( minusList )
-import TCE ( TCE(..), UniqFM )
-import TVE ( mkTVE, TVE(..) )
-import Spec ( specTy )
-import TcContext ( tcContext )
-import TcBinds ( tcSigs, doSpecPragma )
-import TcGRHSs ( tcGRHSsAndBinds )
-import TcMatches ( tcMatchesFun )
-import TcMonoType ( tcInstanceType )
-import TcPragmas ( tcDictFunPragmas, tcGenPragmas )
-import TcSimplify ( tcSimplifyAndCheck, tcSimplifyThetas )
-import Unify ( unifyTauTy )
-import Unique ( cCallableClassKey, cReturnableClassKey )
-import Util
+import List ( partition )
+import Outputable
\end{code}
Typechecking instance declarations is done in two passes. The first
-pass, made by @tcInstDecls1@,
-collects information to be used in the second pass.
+pass, made by @tcInstDecls1@, collects information to be used in the
+second pass.
This pre-processed info includes the as-yet-unprocessed bindings
inside the instance declaration. These are type-checked in the second
all the instance and value decls. Indeed that's the reason we need
two passes over the instance decls.
- instance c => k (t tvs) where b
-
-\begin{code}
-data InstInfo
- = InstInfo
- Class -- Class, k
- [TyVarTemplate] -- Type variables, tvs
- UniType -- The type at which the class is being
- -- instantiated
- ThetaType -- inst_decl_theta: the original context from the
- -- instance declaration. It constrains (some of)
- -- the TyVarTemplates above
- ThetaType -- dfun_theta: the inst_decl_theta, plus one
- -- element for each superclass; the "Mark
- -- Jones optimisation"
- Id -- The dfun id
- [Id] -- Constant methods (either all or none)
- RenamedMonoBinds -- Bindings, b
- Bool -- True <=> local instance decl
- FAST_STRING -- Name of module where this instance was
- -- defined.
- SrcLoc -- Source location assoc'd with this instance's defn
- [RenamedSig] -- User pragmas recorded for generating specialised methods
-\end{code}
+Here is the overall algorithm.
+Assume that we have an instance declaration
-Here is the overall algorithm. Assume that
+ instance c => k (t tvs) where b
\begin{enumerate}
\item
and $dbinds_super$ bind the superclass dictionaries sd1 \ldots sdm.
\end{enumerate}
-\begin{code}
-tcInstDecls1 :: E -> CE -> TCE -> [RenamedInstDecl] -> NF_TcM (Bag InstInfo)
-tcInstDecls1 e ce tce [] = returnNF_Tc emptyBag
+%************************************************************************
+%* *
+\subsection{Extracting instance decls}
+%* *
+%************************************************************************
-tcInstDecls1 e ce tce (inst_decl : rest)
- = tc_inst_1 inst_decl `thenNF_Tc` \ infos1 ->
- tcInstDecls1 e ce tce rest `thenNF_Tc` \ infos2 ->
- returnNF_Tc (infos1 `unionBags` infos2)
+Gather up the instance declarations from their various sources
+
+\begin{code}
+tcInstDecls1 :: PackageInstEnv
+ -> PersistentRenamerState
+ -> HomeSymbolTable -- Contains instances
+ -> TcEnv -- Contains IdInfo for dfun ids
+ -> (Name -> Maybe Fixity) -- for deriving Show and Read
+ -> Module -- Module for deriving
+ -> [TyCon]
+ -> [RenamedHsDecl]
+ -> TcM (PackageInstEnv, InstEnv, [InstInfo], RenamedHsBinds)
+
+tcInstDecls1 inst_env0 prs hst unf_env get_fixity mod tycons decls
+ = let
+ inst_decls = [inst_decl | InstD inst_decl <- decls]
+ tycl_decls = [decl | TyClD decl <- decls]
+ clas_decls = filter isClassDecl tycl_decls
+ in
+ -- (1) Do the ordinary instance declarations
+ mapNF_Tc (tcInstDecl1 mod unf_env) inst_decls `thenNF_Tc` \ inst_infos ->
+
+ -- (2) Instances from generic class declarations
+ getGenericInstances mod clas_decls `thenTc` \ generic_inst_info ->
+
+ -- Next, construct the instance environment so far, consisting of
+ -- a) cached non-home-package InstEnv (gotten from pcs) pcs_insts pcs
+ -- b) imported instance decls (not in the home package) inst_env1
+ -- c) other modules in this package (gotten from hst) inst_env2
+ -- d) local instance decls inst_env3
+ -- e) generic instances inst_env4
+ -- The result of (b) replaces the cached InstEnv in the PCS
+ let
+ (local_inst_info, imported_inst_info) = partition iLocal (concat inst_infos)
+
+ imported_dfuns = map (tcAddImportedIdInfo unf_env . iDFunId)
+ imported_inst_info
+ hst_dfuns = foldModuleEnv ((++) . md_insts) [] hst
+ in
+ addInstDFuns inst_env0 imported_dfuns `thenNF_Tc` \ inst_env1 ->
+ addInstDFuns inst_env1 hst_dfuns `thenNF_Tc` \ inst_env2 ->
+ addInstInfos inst_env2 local_inst_info `thenNF_Tc` \ inst_env3 ->
+ addInstInfos inst_env3 generic_inst_info `thenNF_Tc` \ inst_env4 ->
+
+ -- (3) Compute instances from "deriving" clauses;
+ -- note that we only do derivings for things in this module;
+ -- we ignore deriving decls from interfaces!
+ -- This stuff computes a context for the derived instance decl, so it
+ -- needs to know about all the instances possible; hecne inst_env4
+ tcDeriving prs mod inst_env4 get_fixity tycl_decls `thenTc` \ (deriv_inst_info, deriv_binds) ->
+ addInstInfos inst_env4 deriv_inst_info `thenNF_Tc` \ final_inst_env ->
+
+ returnTc (inst_env1,
+ final_inst_env,
+ generic_inst_info ++ deriv_inst_info ++ local_inst_info,
+ deriv_binds)
+
+addInstInfos :: InstEnv -> [InstInfo] -> NF_TcM InstEnv
+addInstInfos inst_env infos = addInstDFuns inst_env (map iDFunId infos)
+
+addInstDFuns :: InstEnv -> [DFunId] -> NF_TcM InstEnv
+addInstDFuns dfuns infos
+ = getDOptsTc `thenTc` \ dflags ->
+ extendInstEnv dflags dfuns infos `bind` \ (inst_env', errs) ->
+ addErrsTc errs `thenNF_Tc_`
+ returnTc inst_env'
where
- tc_inst_1 (InstDecl context class_name ty binds from_here modname imod uprags pragmas src_loc)
- =
- -- Prime error recovery and substitution pruning
- recoverTc emptyBag (
- addSrcLocTc src_loc (
-
- let
- clas = lookupCE ce class_name -- Renamer ensures this can't fail
-
- for_ccallable_or_creturnable
- = class_name == cCallableClass || class_name == cReturnableClass
- where
- cCallableClass = PreludeClass cCallableClassKey bottom
- cReturnableClass = PreludeClass cReturnableClassKey bottom
- bottom = panic "for_ccallable_etc"
-
- -- Make some new type variables, named as in the instance type
- ty_names = extractMonoTyNames (==) ty
- (tve,inst_tyvars,_) = mkTVE ty_names
- in
- -- Check the instance type, including its syntactic constraints
- babyTcMtoTcM (tcInstanceType ce tce tve from_here src_loc ty)
- `thenTc` \ inst_ty ->
-
- -- DEAL WITH THE INSTANCE CONTEXT
- babyTcMtoTcM (tcContext ce tce tve context) `thenTc` \ theta ->
-
- -- SOME BORING AND TURGID CHECKING:
- let
- inst_for_function_type = isFunType inst_ty
- -- sigh; it happens; must avoid tickling inst_tycon
-
- inst_tycon_maybe = getUniDataTyCon_maybe inst_ty
-
- inst_tycon = case inst_tycon_maybe of
- Just (xx,_,_) -> xx
- Nothing -> panic "tcInstDecls1:inst_tycon"
- in
- -------------------------------------------------------------
- -- It is illegal for a normal user's module to declare an
- -- instance for a Prelude-class/Prelude-type instance:
- checkTc (from_here -- really an inst decl in this module
- && fromPreludeCore clas -- prelude class
- && (inst_for_function_type -- prelude type
- || fromPreludeCore inst_tycon)
- && not (fromPrelude modname) -- we aren't compiling a Prelude mod
- )
- (preludeInstanceErr clas inst_ty src_loc) `thenTc_`
-
- -------------------------------------------------------------
- -- It is obviously illegal to have an explicit instance
- -- for something that we are also planning to `derive'.
- -- Note that an instance decl coming in from outside
- -- is probably just telling us about the derived instance
- -- (ToDo: actually check, if possible), so we mustn't flag
- -- it as an error.
- checkTc (from_here
- && not inst_for_function_type
- && clas `derivedFor` inst_tycon)
- (derivingWhenInstanceExistsErr clas inst_tycon) `thenTc_`
-
- -------------------------------------------------------------
- -- A user declaration of a _CCallable/_CReturnable instance
- -- must be for a "boxed primitive" type.
- getSwitchCheckerTc `thenNF_Tc` \ sw_chkr ->
- checkTc (for_ccallable_or_creturnable
- && from_here -- instance defined here
- && not (sw_chkr CompilingPrelude) -- which allows anything
- && (inst_for_function_type || -- a *function*??? hah!
- not (maybeToBool (maybeBoxedPrimType inst_ty)))) -- naughty, naughty
- (nonBoxedPrimCCallErr clas inst_ty src_loc) `thenTc_`
-
- -- END OF TURGIDITY; back to real fun
- -------------------------------------------------------------
-
- if (not inst_for_function_type && clas `derivedFor` inst_tycon) then
- -- Don't use this InstDecl; tcDeriv will make the
- -- InstInfo to be used in later processing.
- returnTc emptyBag
-
- else
- -- Make the dfun id and constant-method ids
- mkInstanceRelatedIds e
- from_here modname pragmas src_loc
- clas inst_tyvars inst_ty theta uprags
- `thenTc` \ (dfun_id, dfun_theta, const_meth_ids) ->
-
- returnTc ( unitBag (
- InstInfo clas inst_tyvars inst_ty theta
- dfun_theta dfun_id const_meth_ids
- binds from_here modname src_loc uprags
- ))
- ))
-\end{code}
+ bind x f = f x
+\end{code}
-Common bit of code shared with @tcDeriving@:
\begin{code}
-mkInstanceRelatedIds e
- from_here modname inst_pragmas locn
- clas
- inst_tyvars inst_ty inst_decl_theta uprags
- = getUniqueTc `thenNF_Tc` \ uniq ->
- let
- (class_tyvar, super_classes, _, class_ops, _, _) = getClassBigSig clas
-
- super_class_theta = super_classes `zip` (repeat inst_ty)
+tcInstDecl1 :: Module -> TcEnv -> RenamedInstDecl -> NF_TcM [InstInfo]
+-- Deal with a single instance declaration
+tcInstDecl1 mod unf_env (InstDecl poly_ty binds uprags maybe_dfun_name src_loc)
+ = -- Prime error recovery, set source location
+ recoverNF_Tc (returnNF_Tc []) $
+ tcAddSrcLoc src_loc $
+
+ -- Type-check all the stuff before the "where"
+ tcHsSigType poly_ty `thenTc` \ poly_ty' ->
+ let
+ (tyvars, theta, clas, inst_tys) = splitDFunTy poly_ty'
+ in
+ (case maybe_dfun_name of
+ Nothing -> -- A source-file instance declaration
- dfun_theta = case inst_decl_theta of
+ -- Check for respectable instance type, and context
+ -- but only do this for non-imported instance decls.
+ -- Imported ones should have been checked already, and may indeed
+ -- contain something illegal in normal Haskell, notably
+ -- instance CCallable [Char]
+ scrutiniseInstanceHead clas inst_tys `thenNF_Tc_`
+ mapNF_Tc scrutiniseInstanceConstraint theta `thenNF_Tc_`
- [] -> [] -- If inst_decl_theta is empty, then we don't
- -- want to have any dict arguments, so that we can
- -- expose the constant methods.
+ -- Make the dfun id and return it
+ newDFunName mod clas inst_tys src_loc `thenNF_Tc` \ dfun_name ->
+ returnNF_Tc (True, dfun_name)
- other -> inst_decl_theta ++ super_class_theta
- -- Otherwise we pass the superclass dictionaries to
- -- the dictionary function; the Mark Jones optimisation.
+ Just dfun_name -> -- An interface-file instance declaration
+ -- Make the dfun id
+ returnNF_Tc (False, dfun_name)
+ ) `thenNF_Tc` \ (is_local, dfun_name) ->
- dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_ty)
+ let
+ dfun_id = mkDictFunId dfun_name clas tyvars inst_tys theta
in
- fixNF_Tc ( \ rec_dfun_id ->
- babyTcMtoNF_TcM (
- tcDictFunPragmas e dfun_ty rec_dfun_id inst_pragmas
- ) `thenNF_Tc` \ dfun_pragma_info ->
- let
- dfun_specenv = mkInstSpecEnv clas inst_ty inst_tyvars dfun_theta
- dfun_info = dfun_pragma_info `addInfo` dfun_specenv
- in
- returnNF_Tc (mkDictFunId uniq clas inst_ty dfun_ty from_here modname dfun_info)
- ) `thenNF_Tc` \ dfun_id ->
-
- -- Make the constant-method ids, if there are no type variables involved
- (if not (null inst_tyvars) -- ToDo: could also do this if theta is null...
- then
- returnNF_Tc []
- else
- let
- inline_mes = [ getTagFromClassOpName v | (InlineSig v _ _) <- uprags ]
-
- mk_const_meth op uniq
- = mkConstMethodId
- uniq
- clas op inst_ty
- meth_ty from_here modname info
- where
- is_elem = isIn "mkInstanceRelatedIds"
-
- info = if tag `is_elem` inline_mes
- then noIdInfo `addInfo_UF` (iWantToBeINLINEd UnfoldAlways)
- else noIdInfo
-
- tenv = [(class_tyvar, inst_ty)]
- tag = getClassOpTag op
- op_ty = getClassOpLocalType op
- meth_ty = instantiateTy tenv op_ty
- -- If you move to a null-theta version, you need a
- -- mkForallTy inst_tyvars here
-
- mk_constm_w_info (op, u, (name, prags)) -- ToDo: chk name?
- = fixNF_Tc ( \ rec_constm_id ->
-
- babyTcMtoNF_TcM (tcGenPragmas e (Just meth_ty) rec_constm_id prags)
- `thenNF_Tc` \ id_info ->
-
- returnNF_Tc (mkConstMethodId u clas op inst_ty meth_ty
- from_here modname id_info)
- )
- where
- tenv = [(class_tyvar, inst_ty)]
- op_ty = getClassOpLocalType op
- meth_ty = instantiateTy tenv op_ty
-
- in
- getUniquesTc (length class_ops) `thenNF_Tc` \ constm_uniqs ->
- (case inst_pragmas of
- ConstantInstancePragma _ name_pragma_pairs ->
- mapNF_Tc mk_constm_w_info (zip3 class_ops constm_uniqs name_pragma_pairs)
-
- other_inst_pragmas ->
- returnNF_Tc (zipWith mk_const_meth class_ops constm_uniqs)
- )
- ) `thenNF_Tc` \ const_meth_ids ->
-
- returnTc (dfun_id, dfun_theta, const_meth_ids)
+ returnTc [InstInfo { iLocal = is_local, iDFunId = dfun_id,
+ iBinds = binds, iPrags = uprags }]
\end{code}
%************************************************************************
%* *
-\subsection{Converting instance info into suitable InstEnvs}
+\subsection{Extracting generic instance declaration from class declarations}
%* *
%************************************************************************
-\begin{code}
-buildInstanceEnvs :: Bag InstInfo
- -> TcM InstanceMapper
+@getGenericInstances@ extracts the generic instance declarations from a class
+declaration. For exmaple
-buildInstanceEnvs info
- = let
- cmp :: InstInfo -> InstInfo -> TAG_
- (InstInfo c1 _ _ _ _ _ _ _ _ _ _ _) `cmp` (InstInfo c2 _ _ _ _ _ _ _ _ _ _ _)
- = if c1 == c2 then EQ_ else if c1 < c2 then LT_ else GT_
+ class C a where
+ op :: a -> a
+
+ op{ x+y } (Inl v) = ...
+ op{ x+y } (Inr v) = ...
+ op{ x*y } (v :*: w) = ...
+ op{ 1 } Unit = ...
+
+gives rise to the instance declarations
+
+ instance C (x+y) where
+ op (Inl v) = ...
+ op (Inr v) = ...
+
+ instance C (x*y) where
+ op (v :*: w) = ...
+
+ instance C 1 where
+ op Unit = ...
- info_by_class = equivClasses cmp (bagToList info)
- in
- mapTc buildInstanceEnv info_by_class `thenTc` \ inst_env_entries ->
- let
- class_lookup_maybe_fn
- :: Class
- -> Maybe (ClassInstEnv, (ClassOp -> SpecEnv))
- class_lookup_fn
- :: InstanceMapper
-
- class_lookup_maybe_fn = mkLookupFun (==) inst_env_entries
-
- class_lookup_fn c
- = case class_lookup_maybe_fn c of
- Nothing -> (nullMEnv, \ o -> nullSpecEnv)
- Just xx -> xx
- in
- returnTc class_lookup_fn
-\end{code}
\begin{code}
-buildInstanceEnv :: [InstInfo] -- Non-empty, and all for same class
- -> TcM (Class, (ClassInstEnv, (ClassOp -> SpecEnv)))
+getGenericInstances :: Module -> [RenamedTyClDecl] -> TcM [InstInfo]
+getGenericInstances mod class_decls
+ = mapTc (get_generics mod) class_decls `thenTc` \ gen_inst_infos ->
+ let
+ gen_inst_info = concat gen_inst_infos
+ in
+ getDOptsTc `thenTc` \ dflags ->
+ ioToTc (dumpIfSet_dyn dflags Opt_D_dump_deriv "Generic instances"
+ (vcat (map pprInstInfo gen_inst_info)))
+ `thenNF_Tc_`
+ returnTc gen_inst_info
+
+get_generics mod decl@(ClassDecl context class_name tyvar_names
+ fundeps class_sigs def_methods
+ name_list loc)
+ | null groups
+ = returnTc [] -- The comon case:
+ -- no generic default methods, or
+ -- its an imported class decl (=> has no methods at all)
+
+ | otherwise -- A local class decl with generic default methods
+ = recoverNF_Tc (returnNF_Tc []) $
+ tcAddDeclCtxt decl $
+ tcLookupClass class_name `thenTc` \ clas ->
+
+ -- Make an InstInfo out of each group
+ mapTc (mkGenericInstance mod clas loc) groups `thenTc` \ inst_infos ->
+
+ -- Check that there is only one InstInfo for each type constructor
+ -- The main way this can fail is if you write
+ -- f {| a+b |} ... = ...
+ -- f {| x+y |} ... = ...
+ -- Then at this point we'll have an InstInfo for each
+ let
+ tc_inst_infos :: [(TyCon, InstInfo)]
+ tc_inst_infos = [(simpleInstInfoTyCon i, i) | i <- inst_infos]
-buildInstanceEnv inst_infos@(info_for_one@(InstInfo clas _ _ _ _ _ _ _ _ _ _ _) : rest)
- = let
- ops = getClassOps clas
- no_of_ops = length ops
+ bad_groups = [group | group <- equivClassesByUniq get_uniq tc_inst_infos,
+ length group > 1]
+ get_uniq (tc,_) = getUnique tc
in
- foldlTc addClassInstance
- (nullMEnv, nOfThem no_of_ops nullSpecEnv)
- inst_infos `thenTc` \ (class_inst_env, op_inst_envs) ->
+ mapTc (addErrTc . dupGenericInsts) bad_groups `thenTc_`
+
+ -- Check that there is an InstInfo for each generic type constructor
let
- class_op_maybe_fn :: ClassOp -> Maybe SpecEnv
- class_op_fn :: ClassOp -> SpecEnv
-
- class_op_maybe_fn = mkLookupFun (==) (ops `zip` op_inst_envs)
- -- They compare by ClassOp tags
- class_op_fn op
- = case class_op_maybe_fn op of
- Nothing -> nullSpecEnv
- Just xx -> xx
+ missing = genericTyCons `minusList` [tc | (tc,_) <- tc_inst_infos]
in
- returnTc (clas, (class_inst_env, class_op_fn))
-\end{code}
+ checkTc (null missing) (missingGenericInstances missing) `thenTc_`
-\begin{code}
-addClassInstance
- :: (ClassInstEnv, [SpecEnv])
- -> InstInfo
- -> TcM (ClassInstEnv, [SpecEnv]) -- One SpecEnv for each class op
-
-addClassInstance
- (class_inst_env, op_spec_envs)
- (InstInfo clas inst_tyvars inst_ty inst_decl_theta dfun_theta dfun_id const_meth_ids _ _ _ src_loc _)
- = getSwitchCheckerTc `thenNF_Tc` \ sw_chkr ->
- -- We anly add specialised/overlapped instances
- -- if we are specialising the overloading
---
--- ToDo ... This causes getConstMethodId errors!
---
--- if is_plain_instance inst_ty || sw_chkr SpecialiseOverloaded
--- then
-
- -- Insert into the class_inst_env first
- checkMaybeErrTc (addClassInst clas class_inst_env inst_ty dfun_id inst_tyvars dfun_theta src_loc)
- dupInstErr `thenTc` \ class_inst_env' ->
- let
- -- Adding the classop instances can't fail if the class instance itself didn't
- op_spec_envs' = case const_meth_ids of
- [] -> op_spec_envs
- other -> zipWith add_const_meth op_spec_envs const_meth_ids
- in
- returnTc (class_inst_env', op_spec_envs')
-
--- else
--- -- Drop this specialised/overlapped instance
--- returnTc (class_inst_env, op_spec_envs)
+ returnTc inst_infos
where
- add_const_meth spec_env meth_id
- = addOneToSpecEnv spec_env (SpecInfo (Just inst_ty:nothings) 1 meth_id)
- where
- (const_meth_tyvars,_) = splitForalls (getIdUniType meth_id)
- nothings = [Nothing | _ <- const_meth_tyvars]
- -- This only works if the constant method id only has its local polymorphism.
- -- If you want to have constant methods for
- -- instance Foo (a,b,c) where
- -- op x = ...
- -- then the constant method will be polymorphic in a,b,c, and
- -- the SpecInfo will need to be elaborated.
+ -- Group the declarations by type pattern
+ groups :: [(RenamedHsType, RenamedMonoBinds)]
+ groups = assocElts (getGenericBinds def_methods)
+
+
+---------------------------------
+getGenericBinds :: RenamedMonoBinds -> Assoc RenamedHsType RenamedMonoBinds
+ -- Takes a group of method bindings, finds the generic ones, and returns
+ -- them in finite map indexed by the type parameter in the definition.
+
+getGenericBinds EmptyMonoBinds = emptyAssoc
+getGenericBinds (AndMonoBinds m1 m2)
+ = plusAssoc_C AndMonoBinds (getGenericBinds m1) (getGenericBinds m2)
+
+getGenericBinds (FunMonoBind id infixop matches loc)
+ = mapAssoc wrap (foldl add emptyAssoc matches)
+ -- Using foldl not foldr is vital, else
+ -- we reverse the order of the bindings!
+ where
+ add env match = case maybeGenericMatch match of
+ Nothing -> env
+ Just (ty, match') -> extendAssoc_C (++) env (ty, [match'])
+
+ wrap ms = FunMonoBind id infixop ms loc
+
+---------------------------------
+mkGenericInstance :: Module -> Class -> SrcLoc
+ -> (RenamedHsType, RenamedMonoBinds)
+ -> TcM InstInfo
+
+mkGenericInstance mod clas loc (hs_ty, binds)
+ -- Make a generic instance declaration
+ -- For example: instance (C a, C b) => C (a+b) where { binds }
+ = -- Extract the universally quantified type variables
+ tcTyVars (nameSetToList (extractHsTyVars hs_ty))
+ (kcHsSigType hs_ty) `thenTc` \ tyvars ->
+ tcExtendTyVarEnv tyvars $
+
+ -- Type-check the instance type, and check its form
+ tcHsSigType hs_ty `thenTc` \ inst_ty ->
+ checkTc (validGenericInstanceType inst_ty)
+ (badGenericInstanceType binds) `thenTc_`
+
+ -- Make the dictionary function.
+ newDFunName mod clas [inst_ty] loc `thenNF_Tc` \ dfun_name ->
+ let
+ inst_theta = [mkClassPred clas [mkTyVarTy tv] | tv <- tyvars]
+ inst_tys = [inst_ty]
+ dfun_id = mkDictFunId dfun_name clas tyvars inst_tys inst_theta
+ in
+
+ returnTc (InstInfo { iLocal = True, iDFunId = dfun_id,
+ iBinds = binds, iPrags = [] })
\end{code}
+
%************************************************************************
%* *
\subsection{Type-checking instance declarations, pass 2}
%************************************************************************
\begin{code}
-tcInstDecls2 :: E
- -> Bag InstInfo
- -> NF_TcM (LIE, TypecheckedBinds)
+tcInstDecls2 :: [InstInfo]
+ -> NF_TcM (LIE, TcMonoBinds)
-tcInstDecls2 e inst_decls
- = let
- -- Get type variables free in environment. Sadly, there may be
- -- some, because of the dreaded monomorphism restriction
- free_tyvars = tvOfE e
- in
- tcInstDecls2_help e free_tyvars (bagToList inst_decls)
-
-tcInstDecls2_help e free_tyvars [] = returnNF_Tc (nullLIE, EmptyBinds)
-
-tcInstDecls2_help e free_tyvars (inst_decl:inst_decls)
- = tcInstDecl2 e free_tyvars inst_decl `thenNF_Tc` \ (lie1, binds1) ->
- tcInstDecls2_help e free_tyvars inst_decls `thenNF_Tc` \ (lie2, binds2) ->
- returnNF_Tc (lie1 `plusLIE` lie2, binds1 `ThenBinds` binds2)
+tcInstDecls2 inst_decls
+-- = foldBag combine tcInstDecl2 (returnNF_Tc (emptyLIE, EmptyMonoBinds)) inst_decls
+ = foldr combine (returnNF_Tc (emptyLIE, EmptyMonoBinds))
+ (map tcInstDecl2 inst_decls)
+ where
+ combine tc1 tc2 = tc1 `thenNF_Tc` \ (lie1, binds1) ->
+ tc2 `thenNF_Tc` \ (lie2, binds2) ->
+ returnNF_Tc (lie1 `plusLIE` lie2,
+ binds1 `AndMonoBinds` binds2)
\end{code}
-
======= New documentation starts here (Sept 92) ==============
-The main purpose of @tcInstDecl2@ is to return a @Binds@ which defines
+The main purpose of @tcInstDecl2@ is to return a @HsBinds@ which defines
the dictionary function for this instance declaration. For example
\begin{verbatim}
instance Foo a => Foo [a] where
Dict [op1, op2]
\end{verbatim}
-HOWEVER, if the instance decl has no type variables, then it returns a
-bigger @Binds@ with declarations for each method. For example
+HOWEVER, if the instance decl has no context, then it returns a
+bigger @HsBinds@ with declarations for each method. For example
\begin{verbatim}
- instance Foo Int where
+ instance Foo [a] where
op1 x = ...
op2 y = ...
\end{verbatim}
might produce
\begin{verbatim}
- dfun.Foo.Int = Dict [Foo.op1.Int, Foo.op2.Int]
- Foo.op1.Int x = ...
- Foo.op2.Int y = ...
+ dfun.Foo.List a = Dict [Foo.op1.List a, Foo.op2.List a]
+ const.Foo.op1.List a x = ...
+ const.Foo.op2.List a y = ...
\end{verbatim}
This group may be mutually recursive, because (for example) there may
be no method supplied for op2 in which case we'll get
\begin{verbatim}
- Foo.op2.Int = default.Foo.op2 dfun.Foo.Int
+ const.Foo.op2.List a = default.Foo.op2 (dfun.Foo.List a)
\end{verbatim}
that is, the default method applied to the dictionary at this type.
-\begin{code}
-tcInstDecl2 :: E
- -> [TyVar] -- Free in the environment
- -> InstInfo
- -> NF_TcM (LIE, TypecheckedBinds)
-\end{code}
+What we actually produce in either case is:
-First comes the easy case of a non-local instance decl.
+ AbsBinds [a] [dfun_theta_dicts]
+ [(dfun.Foo.List, d)] ++ (maybe) [(const.Foo.op1.List, op1), ...]
+ { d = (sd1,sd2, ..., op1, op2, ...)
+ op1 = ...
+ op2 = ...
+ }
-\begin{code}
-tcInstDecl2 e free_tyvars (InstInfo _ _ _ _ _ _ _ _ False{-not this module-} _ _ _)
- = returnNF_Tc (nullLIE, EmptyBinds)
-\end{code}
+The "maybe" says that we only ask AbsBinds to make global constant methods
+if the dfun_theta is empty.
-Now the case of a general local instance. For an instance declaration, say,
+
+For an instance declaration, say,
instance (C1 a, C2 b) => C (T a b) where
...
is the ``Mark Jones optimisation''. The stuff before the "=>" here
is the @dfun_theta@ below.
-\begin{code}
-tcInstDecl2
- e free_tyvars
- (InstInfo clas template_tyvars inst_ty_tmpl inst_decl_theta dfun_theta
- dfun_id const_meth_ids monobinds True{-from here-} inst_mod locn uprags)
- = let
- origin = InstanceDeclOrigin locn
- in
- recoverTc (nullLIE, EmptyBinds) (
- addSrcLocTc locn (
- pruneSubstTc free_tyvars (
-
- -- Get the class signature
- let (class_tyvar,
- super_classes, sc_sel_ids,
- class_ops, op_sel_ids, defm_ids) = getClassBigSig clas
- in
- -- Prime error recovery and substitution pruning. Instantiate
- -- dictionaries from the specified instance context. These
- -- dicts will be passed into the dictionary-construction
- -- function.
- copyTyVars template_tyvars `thenNF_Tc` \ (inst_env, inst_tyvars, inst_tyvar_tys) ->
- let
- inst_ty = instantiateTy inst_env inst_ty_tmpl
-
- inst_decl_theta' = instantiateThetaTy inst_env inst_decl_theta
- dfun_theta' = instantiateThetaTy inst_env dfun_theta
- sc_theta' = super_classes `zip` (repeat inst_ty)
- in
- newDicts origin sc_theta' `thenNF_Tc` \ sc_dicts' ->
- newDicts origin dfun_theta' `thenNF_Tc` \ dfun_arg_dicts' ->
- newDicts origin inst_decl_theta' `thenNF_Tc` \ inst_decl_dicts' ->
- let
- sc_dicts'_ids = map mkInstId sc_dicts'
- dfun_arg_dicts'_ids = map mkInstId dfun_arg_dicts'
- in
- -- Instantiate the dictionary being constructed
- -- and the dictionary-construction function
- newDicts origin [(clas,inst_ty)] `thenNF_Tc` \ [this_dict] ->
- let
- this_dict_id = mkInstId this_dict
- in
- -- Instantiate method variables
- listNF_Tc [ newMethodId sel_id inst_ty origin locn
- | sel_id <- op_sel_ids
- ] `thenNF_Tc` \ method_ids ->
- let
- method_insts = catMaybes (map isInstId_maybe method_ids)
- -- Extract Insts from those method ids which have them (most do)
- -- See notes on newMethodId
- in
- -- Collect available dictionaries
- let avail_insts = -- These insts are in scope; quite a few, eh?
- [this_dict] ++
- method_insts ++
- dfun_arg_dicts'
- in
- getSwitchCheckerTc `thenNF_Tc` \ sw_chkr ->
- let
- mk_method_expr
- = if sw_chkr OmitDefaultInstanceMethods then
- makeInstanceDeclNoDefaultExpr origin clas method_ids defm_ids inst_mod inst_ty
- else
- makeInstanceDeclDefaultMethodExpr origin this_dict_id class_ops defm_ids inst_ty
- in
- processInstBinds e free_tyvars mk_method_expr
- inst_tyvars avail_insts method_ids monobinds
- `thenTc` \ (insts_needed, method_mbinds) ->
- let
- -- Create the dict and method binds
- dict_bind
- = VarMonoBind this_dict_id (Dictionary sc_dicts'_ids method_ids)
-
- dict_and_method_binds
- = dict_bind `AndMonoBinds` method_mbinds
- in
- -- Check the overloading constraints of the methods and superclasses
- -- The global tyvars must be a fixed point of the substitution
- applyTcSubstAndCollectTyVars free_tyvars `thenNF_Tc` \ real_free_tyvars ->
- tcSimplifyAndCheck
- True -- Top level
- real_free_tyvars -- Global tyvars
- inst_tyvars -- Local tyvars
- avail_insts
- (sc_dicts' ++ insts_needed) -- Need to get defns for all these
- (BindSigCtxt method_ids)
- `thenTc` \ (const_insts, super_binds) ->
-
- -- Check that we *could* construct the superclass dictionaries,
- -- even though we are *actually* going to pass the superclass dicts in;
- -- the check ensures that the caller will never have a problem building
- -- them.
- tcSimplifyAndCheck
- False -- Doesn't matter; more efficient this way
- real_free_tyvars -- Global tyvars
- inst_tyvars -- Local tyvars
- inst_decl_dicts' -- The instance dictionaries available
- sc_dicts' -- The superclass dicationaries reqd
- SuperClassSigCtxt
- `thenTc_`
- -- Ignore the result; we're only doing
- -- this to make sure it can be done.
-
- -- Now process any SPECIALIZE pragmas for the methods
- let
- spec_sigs = [ s | s@(SpecSig _ _ _ _) <- uprags ]
-
- get_const_method_id name
- = const_meth_ids !! ((getTagFromClassOpName name) - 1)
- in
- tcSigs e [] spec_sigs `thenTc` \ sig_info ->
-
- mapAndUnzipTc (doSpecPragma e get_const_method_id) sig_info
- `thenTc` \ (spec_binds_s, spec_lie_s) ->
- let
- spec_lie = foldr plusLIE nullLIE spec_lie_s
- spec_binds = foldr AndMonoBinds EmptyMonoBinds spec_binds_s
-
- -- Complete the binding group, adding any spec_binds
- inst_binds
- = AbsBinds
- inst_tyvars
- dfun_arg_dicts'_ids
- ((this_dict_id,dfun_id) : (method_ids `zip` const_meth_ids))
- -- const_meth_ids will often be empty
- super_binds
- (RecBind dict_and_method_binds)
-
- `ThenBinds`
- SingleBind (NonRecBind spec_binds)
- in
- -- Back-substitute
- applyTcSubstToBinds inst_binds `thenNF_Tc` \ final_inst_binds ->
-
- returnTc (mkLIE const_insts `plusLIE` spec_lie,
- final_inst_binds)
- )))
-\end{code}
+First comes the easy case of a non-local instance decl.
-@mkMethodId@ manufactures an id for a local method.
-It's rather turgid stuff, because there are two cases:
+\begin{code}
+tcInstDecl2 :: InstInfo -> NF_TcM (LIE, TcMonoBinds)
- (a) For methods with no local polymorphism, we can make an Inst of the
- class-op selector function and a corresp InstId;
- which is good because then other methods which call
- this one will do so directly.
+tcInstDecl2 (InstInfo { iLocal = is_local, iDFunId = dfun_id,
+ iBinds = monobinds, iPrags = uprags })
+ | not is_local
+ = returnNF_Tc (emptyLIE, EmptyMonoBinds)
- (b) For methods with local polymorphism, we can't do this. For example,
+ | otherwise
+ = -- Prime error recovery
+ recoverNF_Tc (returnNF_Tc (emptyLIE, EmptyMonoBinds)) $
+ tcAddSrcLoc (getSrcLoc dfun_id) $
- class Foo a where
- op :: (Num b) => a -> b -> a
+ -- Instantiate the instance decl with tc-style type variables
+ tcInstId dfun_id `thenNF_Tc` \ (inst_tyvars', dfun_theta', dict_ty') ->
+ let
+ (clas, inst_tys') = splitDictTy dict_ty'
+ origin = InstanceDeclOrigin
- Here the type of the class-op-selector is
+ (class_tyvars, sc_theta, _, op_items) = classBigSig clas
- forall a b. (Foo a, Num b) => a -> b -> a
+ dm_ids = [dm_id | (_, DefMeth dm_id) <- op_items]
+ sel_names = [idName sel_id | (sel_id, _) <- op_items]
- The locally defined method at (say) type Float will have type
+ -- Instantiate the super-class context with inst_tys
+ sc_theta' = substClasses (mkTopTyVarSubst class_tyvars inst_tys') sc_theta
- forall b. (Num b) => Float -> b -> Float
+ -- Find any definitions in monobinds that aren't from the class
+ bad_bndrs = collectMonoBinders monobinds `minusList` sel_names
- and the one is not an instance of the other.
+ -- The type variable from the dict fun actually scope
+ -- over the bindings. They were gotten from
+ -- the original instance declaration
+ (inst_tyvars, _) = splitForAllTys (idType dfun_id)
+ in
+ -- Check that all the method bindings come from this class
+ mapTc (addErrTc . badMethodErr clas) bad_bndrs `thenNF_Tc_`
+
+ -- Create dictionary Ids from the specified instance contexts.
+ newClassDicts origin sc_theta' `thenNF_Tc` \ (sc_dicts, sc_dict_ids) ->
+ newDicts origin dfun_theta' `thenNF_Tc` \ (dfun_arg_dicts, dfun_arg_dicts_ids) ->
+ newClassDicts origin [(clas,inst_tys')] `thenNF_Tc` \ (this_dict, [this_dict_id]) ->
+
+ tcExtendTyVarEnvForMeths inst_tyvars inst_tyvars' (
+ tcExtendGlobalValEnv dm_ids (
+ -- Default-method Ids may be mentioned in synthesised RHSs
+
+ mapAndUnzip3Tc (tcMethodBind clas origin inst_tyvars' inst_tys'
+ dfun_theta'
+ monobinds uprags True)
+ op_items
+ )) `thenTc` \ (method_binds_s, insts_needed_s, meth_lies_w_ids) ->
+
+ -- Deal with SPECIALISE instance pragmas by making them
+ -- look like SPECIALISE pragmas for the dfun
+ let
+ dfun_prags = [SpecSig (idName dfun_id) ty loc | SpecInstSig ty loc <- uprags]
+ in
+ tcExtendGlobalValEnv [dfun_id] (
+ tcSpecSigs dfun_prags
+ ) `thenTc` \ (prag_binds, prag_lie) ->
- So for these we just make a local (non-Inst) id with a suitable type.
+ -- Check the overloading constraints of the methods and superclasses
-How disgusting.
+ -- tcMethodBind has checked that the class_tyvars havn't
+ -- been unified with each other or another type, but we must
+ -- still zonk them before passing them to tcSimplifyAndCheck
+ zonkTcSigTyVars inst_tyvars' `thenNF_Tc` \ zonked_inst_tyvars ->
+ let
+ inst_tyvars_set = mkVarSet zonked_inst_tyvars
-\begin{code}
-newMethodId sel_id inst_ty origin loc
- = let (sel_tyvars,sel_theta,sel_tau) = splitType (getIdUniType sel_id)
- (_:meth_theta) = sel_theta -- The local theta is all except the
- -- first element of the context
- in
- case sel_tyvars of
- -- Ah! a selector for a class op with no local polymorphism
- -- Build an Inst for this
- [clas_tyvar] -> newMethod origin sel_id [inst_ty] `thenNF_Tc` \ inst ->
- returnNF_Tc (mkInstId inst)
-
- -- Ho! a selector for a class op with local polymorphism.
- -- Just make a suitably typed local id for this
- (clas_tyvar:local_tyvars) ->
- let
- method_ty = instantiateTy [(clas_tyvar,inst_ty)]
- (mkSigmaTy local_tyvars meth_theta sel_tau)
- in
- getUniqueTc `thenNF_Tc` \ uniq ->
- returnNF_Tc (mkUserLocal (getOccurrenceName sel_id) uniq method_ty loc)
-\end{code}
+ (meth_lies, meth_ids) = unzip meth_lies_w_ids
-This function makes a default method which calls the global default method, at
-the appropriate instance type.
+ -- These insts are in scope; quite a few, eh?
+ avail_insts = this_dict `plusLIE`
+ dfun_arg_dicts `plusLIE`
+ sc_dicts `plusLIE`
+ unionManyBags meth_lies
-See the notes under default decls in TcClassDcl.lhs.
+ methods_lie = plusLIEs insts_needed_s
+ in
-\begin{code}
-makeInstanceDeclDefaultMethodExpr
- :: InstOrigin
- -> Id
- -> [ClassOp]
- -> [Id]
- -> UniType
- -> Int
- -> NF_TcM TypecheckedExpr
+ -- Ditto method bindings
+ tcAddErrCtxt methodCtxt (
+ tcSimplifyAndCheck
+ (ptext SLIT("instance declaration context"))
+ inst_tyvars_set -- Local tyvars
+ avail_insts
+ methods_lie
+ ) `thenTc` \ (const_lie1, lie_binds1) ->
+
+ -- Now do the simplification again, this time to get the
+ -- bindings; this time we use an enhanced "avails"
+ -- Ignore errors because they come from the *previous* tcSimplify
+ discardErrsTc (
+ tcSimplifyAndCheck
+ (ptext SLIT("instance declaration context"))
+ inst_tyvars_set
+ dfun_arg_dicts -- NB! Don't include this_dict here, else the sc_dicts
+ -- get bound by just selecting from this_dict!!
+ sc_dicts
+ ) `thenTc` \ (const_lie2, lie_binds2) ->
-makeInstanceDeclDefaultMethodExpr origin this_dict_id class_ops defm_ids inst_ty tag
- = let
- (tyvar_tmpls, local_theta, _) = splitType (getClassOpLocalType class_op)
- in
- copyTyVars tyvar_tmpls `thenNF_Tc` \ (inst_env, tyvars, tys) ->
- let
- inst_theta = instantiateThetaTy inst_env local_theta
- in
- newDicts origin inst_theta `thenNF_Tc` \ local_dict_insts ->
+
+ -- Create the result bindings
let
- local_dicts = map mkInstId local_dict_insts
+ dict_constr = classDataCon clas
+ scs_and_meths = sc_dict_ids ++ meth_ids
+
+ dict_rhs
+ | null scs_and_meths
+ = -- Blatant special case for CCallable, CReturnable
+ -- If the dictionary is empty then we should never
+ -- select anything from it, so we make its RHS just
+ -- emit an error message. This in turn means that we don't
+ -- mention the constructor, which doesn't exist for CCallable, CReturnable
+ -- Hardly beautiful, but only three extra lines.
+ HsApp (TyApp (HsVar eRROR_ID) [idType this_dict_id])
+ (HsLit (HsString msg))
+
+ | otherwise -- The common case
+ = mkHsConApp dict_constr inst_tys' (map HsVar (sc_dict_ids ++ meth_ids))
+ -- We don't produce a binding for the dict_constr; instead we
+ -- rely on the simplifier to unfold this saturated application
+ -- We do this rather than generate an HsCon directly, because
+ -- it means that the special cases (e.g. dictionary with only one
+ -- member) are dealt with by the common MkId.mkDataConWrapId code rather
+ -- than needing to be repeated here.
+
+ where
+ msg = _PK_ ("Compiler error: bad dictionary " ++ showSDoc (ppr clas))
+
+ dict_bind = VarMonoBind this_dict_id dict_rhs
+ method_binds = andMonoBindList method_binds_s
+
+ main_bind
+ = AbsBinds
+ zonked_inst_tyvars
+ dfun_arg_dicts_ids
+ [(inst_tyvars', dfun_id, this_dict_id)]
+ emptyNameSet -- No inlines (yet)
+ (lie_binds1 `AndMonoBinds`
+ lie_binds2 `AndMonoBinds`
+ method_binds `AndMonoBinds`
+ dict_bind)
in
- returnNF_Tc (
- mkTyLam tyvars (
- mkDictLam local_dicts (
- mkDictApp (mkTyApp (Var defm_id)
- (inst_ty : tys))
- (this_dict_id:local_dicts)))
- )
- where
- idx = tag - 1
- class_op = class_ops !! idx
- defm_id = defm_ids !! idx
-
-
-makeInstanceDeclNoDefaultExpr
- :: InstOrigin
- -> Class
- -> [Id]
- -> [Id]
- -> FAST_STRING
- -> UniType
- -> Int
- -> NF_TcM TypecheckedExpr
-
-makeInstanceDeclNoDefaultExpr origin clas method_ids defm_ids inst_mod inst_ty tag
- = specTy origin (getIdUniType method_id) `thenNF_Tc` \ (tyvars, dicts, tau) ->
-
- (if not err_defm then
- pprTrace "Warning: "
- (ppCat [ppStr "Omitted default method for",
- ppr PprForUser clas_op, ppStr "in instance",
- ppPStr clas_name, pprParendUniType PprForUser inst_ty])
- else id) (
-
- returnNF_Tc (mkTyLam tyvars (
- mkDictLam (map mkInstId dicts) (
- App (mkTyApp (Var pAT_ERROR_ID) [tau])
- (Lit (StringLit (_PK_ error_msg))))))
- )
- where
- idx = tag - 1
- clas_op = (getClassOps clas) !! idx
- method_id = method_ids !! idx
- defm_id = defm_ids !! idx
-
- Just (_, _, err_defm) = isDefaultMethodId_maybe defm_id
-
- error_msg = "%E" -- => No explicit method for \"
- ++ escErrorMsg error_str
-
- error_str = _UNPK_ inst_mod ++ "." ++ _UNPK_ clas_name ++ "."
- ++ (ppShow 80 (ppr PprForUser inst_ty)) ++ "."
- ++ (ppShow 80 (ppr PprForUser clas_op)) ++ "\""
-
- (_, clas_name) = getOrigName clas
+ returnTc (const_lie1 `plusLIE` const_lie2 `plusLIE` prag_lie,
+ main_bind `AndMonoBinds` prag_binds)
\end{code}
%************************************************************************
%* *
-\subsection{Processing each method}
+\subsection{Checking for a decent instance type}
%* *
%************************************************************************
-@processInstBinds@ returns a @MonoBinds@ which binds
-all the method ids (which are passed in). It is used
- - both for instance decls,
- - and to compile the default-method declarations in a class decl.
-
-Any method ids which don't have a binding have a suitable default
-binding created for them. The actual right-hand side used is
-created using a function which is passed in, because the right thing to
-do differs between instance and class decls.
-
-\begin{code}
-processInstBinds
- :: E
- -> [TyVar] -- Free in envt
-
- -> (Int -> NF_TcM TypecheckedExpr) -- Function to make
- -- default method
-
- -> [TyVar] -- Tyvars for this instance decl
+@scrutiniseInstanceHead@ checks the type {\em and} its syntactic constraints:
+it must normally look like: @instance Foo (Tycon a b c ...) ...@
- -> [Inst] -- available Insts
-
- -> [Id] -- Local method ids
- -- (instance tyvars are free
- -- in their types),
- -- in tag order
- -> RenamedMonoBinds
-
- -> TcM ([Inst], -- These are required
- TypecheckedMonoBinds)
-
-processInstBinds e free_tyvars mk_method_expr inst_tyvars
- avail_insts method_ids monobinds
- =
- -- Process the explicitly-given method bindings
- processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids monobinds
- `thenTc` (\ (tags, insts_needed_in_methods, method_binds) ->
-
- -- Find the methods not handled, and make default method bindings for them.
- let unmentioned_tags = [1.. length method_ids] `minusList` tags
- in
- makeDefaultMethods mk_method_expr unmentioned_tags method_ids
- `thenNF_Tc` (\ default_monobinds ->
+The exceptions to this syntactic checking: (1)~if the @GlasgowExts@
+flag is on, or (2)~the instance is imported (they must have been
+compiled elsewhere). In these cases, we let them go through anyway.
- returnTc (insts_needed_in_methods,
- method_binds `AndMonoBinds` default_monobinds)
- ))
-\end{code}
+We can also have instances for functions: @instance Foo (a -> b) ...@.
\begin{code}
-processInstBinds1
- :: E
- -> [TyVar] -- Global free tyvars
- -> [TyVar] -- Tyvars for this instance decl
- -> [Inst] -- available Insts
- -> [Id] -- Local method ids (instance tyvars are free),
- -- in tag order
- -> RenamedMonoBinds
- -> TcM ([Int], -- Class-op tags accounted for
- [Inst], -- These are required
- TypecheckedMonoBinds)
-
-processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids EmptyMonoBinds
- = returnTc ([], [], EmptyMonoBinds)
-
-processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids (AndMonoBinds mb1 mb2)
- = processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids mb1
- `thenTc` \ (op_tags1,dicts1,method_binds1) ->
- processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids mb2
- `thenTc` \ (op_tags2,dicts2,method_binds2) ->
- returnTc (op_tags1 ++ op_tags2,
- dicts1 ++ dicts2,
- AndMonoBinds method_binds1 method_binds2)
-\end{code}
+scrutiniseInstanceConstraint pred
+ = getDOptsTc `thenTc` \ dflags -> case () of
+ ()
+ | dopt Opt_AllowUndecidableInstances dflags
+ -> returnNF_Tc ()
+
+ | Just (clas,tys) <- getClassTys_maybe pred,
+ all isTyVarTy tys
+ -> returnNF_Tc ()
+
+ | otherwise
+ -> addErrTc (instConstraintErr pred)
+
+scrutiniseInstanceHead clas inst_taus
+ = getDOptsTc `thenTc` \ dflags -> case () of
+ ()
+ | -- CCALL CHECK
+ -- A user declaration of a CCallable/CReturnable instance
+ -- must be for a "boxed primitive" type.
+ (clas `hasKey` cCallableClassKey
+ && not (ccallable_type dflags first_inst_tau))
+ ||
+ (clas `hasKey` cReturnableClassKey
+ && not (creturnable_type first_inst_tau))
+ -> addErrTc (nonBoxedPrimCCallErr clas first_inst_tau)
+
+ -- Allow anything for AllowUndecidableInstances
+ | dopt Opt_AllowUndecidableInstances dflags
+ -> returnNF_Tc ()
+
+ -- If GlasgowExts then check at least one isn't a type variable
+ | dopt Opt_GlasgowExts dflags
+ -> if all isTyVarTy inst_taus
+ then addErrTc (instTypeErr clas inst_taus
+ (text "There must be at least one non-type-variable in the instance head"))
+ else returnNF_Tc ()
+
+ -- WITH HASKELL 1.4, MUST HAVE C (T a b c)
+ | not (length inst_taus == 1 &&
+ maybeToBool maybe_tycon_app && -- Yes, there's a type constuctor
+ not (isSynTyCon tycon) && -- ...but not a synonym
+ all isTyVarTy arg_tys && -- Applied to type variables
+ length (varSetElems (tyVarsOfTypes arg_tys)) == length arg_tys
+ -- This last condition checks that all the type variables are distinct
+ )
+ -> addErrTc (instTypeErr clas inst_taus
+ (text "the instance type must be of form (T a b c)" $$
+ text "where T is not a synonym, and a,b,c are distinct type variables")
+ )
+
+ | otherwise
+ -> returnNF_Tc ()
-\begin{code}
-processInstBinds1 e free_tyvars inst_tyvars avail_insts method_ids mbind
- =
- -- Find what class op is being defined here. The complication is
- -- that we could have a PatMonoBind or a FunMonoBind. If the
- -- former, it should only bind a single variable, or else we're in
- -- trouble (I'm not sure what the static semantics of methods
- -- defined in a pattern binding with multiple patterns is!)
- -- Renamer has reduced us to these two cases.
- let
- (op,locn) = case mbind of
- FunMonoBind op _ locn -> (op, locn)
- PatMonoBind (VarPatIn op) _ locn -> (op, locn)
-
- origin = InstanceDeclOrigin locn
- in
- addSrcLocTc locn (
+ where
+ (first_inst_tau : _) = inst_taus
- -- Make a method id for the method
- let tag = getTagFromClassOpName op
- method_id = method_ids !! (tag-1)
- method_ty = getIdUniType method_id
- in
- specTy origin method_ty `thenNF_Tc` \ (method_tyvars, method_dicts, method_tau) ->
-
- -- Build the result
- case (method_tyvars, method_dicts) of
-
- ([],[]) -> -- The simple case; no local polymorphism or overloading in the method
-
- -- Type check the method itself
- tcMethodBind e method_id method_tau mbind `thenTc` \ (mbind', lieIop) ->
-
- -- Make sure that the instance tyvars havn't been
- -- unified with each other or with the method tyvars.
- -- The global tyvars must be a fixed point of the substitution
- applyTcSubstAndCollectTyVars free_tyvars `thenNF_Tc` \ real_free_tyvars ->
- checkSigTyVars real_free_tyvars inst_tyvars method_tau method_tau
- (MethodSigCtxt op method_tau) `thenTc_`
-
- returnTc ([tag], unMkLIE lieIop, mbind')
-
- other -> -- It's a locally-polymorphic and/or overloaded method; UGH!
-
- -- Make a new id for (a) the local, non-overloaded method
- -- and (b) the locally-overloaded method
- -- The latter is needed just so we can return an AbsBinds wrapped
- -- up inside a MonoBinds.
- newLocalWithGivenTy op method_tau `thenNF_Tc` \ local_meth_id ->
- newLocalWithGivenTy op method_ty `thenNF_Tc` \ copy_meth_id ->
-
- -- Typecheck the method
- tcMethodBind e local_meth_id method_tau mbind `thenTc` \ (mbind', lieIop) ->
-
- -- Make sure that the instance tyvars haven't been
- -- unified with each other or with the method tyvars.
- -- The global tyvars must be a fixed point of the substitution
- applyTcSubstAndCollectTyVars free_tyvars `thenNF_Tc` \ real_free_tyvars ->
- checkSigTyVars real_free_tyvars (method_tyvars ++ inst_tyvars) method_tau method_tau
- (MethodSigCtxt op method_tau) `thenTc_`
-
- -- Check the overloading part of the signature.
- -- Simplify everything fully, even though some
- -- constraints could "really" be left to the next
- -- level out. The case which forces this is
- --
- -- class Foo a where { op :: Bar a => a -> a }
- --
- -- Here we must simplify constraints on "a" to catch all
- -- the Bar-ish things.
- tcSimplifyAndCheck
- False -- Not top level
- real_free_tyvars
- (inst_tyvars ++ method_tyvars)
- (method_dicts ++ avail_insts)
- (unMkLIE lieIop)
- (MethodSigCtxt op method_ty) `thenTc` \ (f_dicts, dict_binds) ->
-
- returnTc ([tag],
- f_dicts,
- VarMonoBind method_id
- (Let
- (AbsBinds
- method_tyvars
- (map mkInstId method_dicts)
- [(local_meth_id, copy_meth_id)]
- dict_binds
- (NonRecBind mbind'))
- (Var copy_meth_id)))
- )
-\end{code}
+ -- Stuff for algebraic or -> type
+ maybe_tycon_app = splitTyConApp_maybe first_inst_tau
+ Just (tycon, arg_tys) = maybe_tycon_app
-\begin{code}
-tcMethodBind :: E -> Id -> UniType -> RenamedMonoBinds
- -> TcM (TypecheckedMonoBinds, LIE)
-
-tcMethodBind e meth_id meth_ty (FunMonoBind name matches locn)
- = addSrcLocTc locn (
- tcMatchesFun e name meth_ty matches `thenTc` \ (rhs', lie) ->
- returnTc (FunMonoBind meth_id rhs' locn, lie)
- )
-
-tcMethodBind e meth_id meth_ty (PatMonoBind pat grhss_and_binds locn)
- -- pat is sure to be a (VarPatIn op)
- = addSrcLocTc locn (
- tcGRHSsAndBinds e grhss_and_binds `thenTc` \ (grhss_and_binds', lie, rhs_ty) ->
- unifyTauTy meth_ty rhs_ty (PatMonoBindsCtxt pat grhss_and_binds) `thenTc_`
- returnTc (PatMonoBind (VarPat meth_id) grhss_and_binds' locn, lie)
- )
+ ccallable_type dflags ty = isFFIArgumentTy dflags False {- Not safe call -} ty
+ creturnable_type ty = isFFIResultTy ty
\end{code}
-Creates bindings for the default methods, being the application of the
-appropriate global default method to the type of this instance decl.
-
-\begin{code}
-makeDefaultMethods
- :: (Int -> NF_TcM TypecheckedExpr) -- Function to make
- -- default method
- -> [Int] -- Tags for methods required
- -> [Id] -- Method names to bind, in tag order
- -> NF_TcM TypecheckedMonoBinds
-
-
-makeDefaultMethods mk_method_expr [] method_ids
- = returnNF_Tc EmptyMonoBinds
-
-makeDefaultMethods mk_method_expr (tag:tags) method_ids
- = mk_method_expr tag `thenNF_Tc` \ rhs ->
- makeDefaultMethods mk_method_expr tags method_ids `thenNF_Tc` \ meth_binds ->
-
- returnNF_Tc ((VarMonoBind method_id rhs) `AndMonoBinds` meth_binds)
- where
- method_id = method_ids !! (tag-1)
-\end{code}
-
%************************************************************************
%* *
-\subsection{Type-checking specialise instance pragmas}
+\subsection{Error messages}
%* *
%************************************************************************
\begin{code}
-tcSpecInstSigs :: E -> CE -> TCE
- -> Bag InstInfo -- inst decls seen (declared and derived)
- -> [RenamedSpecialisedInstanceSig] -- specialise instance upragmas
- -> TcM (Bag InstInfo) -- new, overlapped, inst decls
-
-tcSpecInstSigs e ce tce inst_infos []
- = returnTc emptyBag
-
-tcSpecInstSigs e ce tce inst_infos sigs
- = buildInstanceEnvs inst_infos `thenTc` \ inst_mapper ->
- tc_inst_spec_sigs inst_mapper sigs `thenNF_Tc` \ spec_inst_infos ->
- returnTc spec_inst_infos
- where
- tc_inst_spec_sigs inst_mapper []
- = returnNF_Tc emptyBag
- tc_inst_spec_sigs inst_mapper (sig:sigs)
- = tcSpecInstSig e ce tce inst_infos inst_mapper sig `thenNF_Tc` \ info_sig ->
- tc_inst_spec_sigs inst_mapper sigs `thenNF_Tc` \ info_sigs ->
- returnNF_Tc (info_sig `unionBags` info_sigs)
-
-tcSpecInstSig :: E -> CE -> TCE
- -> Bag InstInfo
- -> InstanceMapper
- -> RenamedSpecialisedInstanceSig
- -> NF_TcM (Bag InstInfo)
-
-tcSpecInstSig e ce tce inst_infos inst_mapper (InstSpecSig class_name ty src_loc)
- = recoverTc emptyBag (
- addSrcLocTc src_loc (
- let
- clas = lookupCE ce class_name -- Renamer ensures this can't fail
-
- -- Make some new type variables, named as in the specialised instance type
- ty_names = extractMonoTyNames (==) ty
- (tmpl_e,inst_tmpls,inst_tmpl_tys) = mkTVE ty_names
- in
- babyTcMtoTcM (tcInstanceType ce tce tmpl_e True src_loc ty)
- `thenTc` \ inst_ty ->
- let
- maybe_tycon = case getUniDataTyCon_maybe inst_ty of
- Just (tc,_,_) -> Just tc
- Nothing -> Nothing
-
- maybe_unspec_inst = lookup_unspec_inst clas maybe_tycon inst_infos
- in
- -- Check that we have a local instance declaration to specialise
- checkMaybeTc maybe_unspec_inst
- (specInstUnspecInstNotFoundErr clas inst_ty src_loc) `thenTc_`
-
- -- Create tvs to substitute for tmpls while simplifying the context
- copyTyVars inst_tmpls `thenNF_Tc` \ (tv_e, inst_tvs, inst_tv_tys) ->
- let
- Just (InstInfo _ unspec_tyvars unspec_inst_ty unspec_theta
- _ _ _ binds True{-from here-} mod _ uprag) = maybe_unspec_inst
-
- subst = case matchTy unspec_inst_ty inst_ty of
- Just subst -> subst
- Nothing -> panic "tcSpecInstSig:matchTy"
-
- subst_theta = instantiateThetaTy subst unspec_theta
- subst_tv_theta = instantiateThetaTy tv_e subst_theta
-
- mk_spec_origin clas ty
- = InstanceSpecOrigin inst_mapper clas ty src_loc
- in
- tcSimplifyThetas mk_spec_origin subst_tv_theta
- `thenTc` \ simpl_tv_theta ->
- let
- simpl_theta = [ (clas, tv_to_tmpl tv) | (clas, tv) <- simpl_tv_theta ]
-
- tv_tmpl_map = inst_tv_tys `zipEqual` inst_tmpl_tys
- tv_to_tmpl tv = assoc "tcSpecInstSig" tv_tmpl_map tv
- in
- mkInstanceRelatedIds e True{-from here-} mod NoInstancePragmas src_loc
- clas inst_tmpls inst_ty simpl_theta uprag
- `thenTc` \ (dfun_id, dfun_theta, const_meth_ids) ->
-
- getSwitchCheckerTc `thenNF_Tc` \ sw_chkr ->
- (if sw_chkr SpecialiseTrace then
- pprTrace "Specialised Instance: "
- (ppAboves [ppCat [if null simpl_theta then ppNil else ppr PprDebug simpl_theta,
- if null simpl_theta then ppNil else ppStr "=>",
- ppr PprDebug clas,
- pprParendUniType PprDebug inst_ty],
- ppCat [ppStr " derived from:",
- if null unspec_theta then ppNil else ppr PprDebug unspec_theta,
- if null unspec_theta then ppNil else ppStr "=>",
- ppr PprDebug clas,
- pprParendUniType PprDebug unspec_inst_ty]])
- else id) (
-
- returnTc (unitBag (InstInfo clas inst_tmpls inst_ty simpl_theta
- dfun_theta dfun_id const_meth_ids
- binds True{-from here-} mod src_loc uprag))
- )))
-
-
-lookup_unspec_inst clas maybe_tycon inst_infos
- = case filter (match_info match_inst_ty) (bagToList inst_infos) of
- [] -> Nothing
- (info:_) -> Just info
+tcAddDeclCtxt decl thing_inside
+ = tcAddSrcLoc loc $
+ tcAddErrCtxt ctxt $
+ thing_inside
where
- match_info match_ty (InstInfo inst_clas _ inst_ty _ _ _ _ _ from_here _ _ _)
- = from_here && clas == inst_clas &&
- match_ty inst_ty && is_plain_instance inst_ty
-
- match_inst_ty = case maybe_tycon of
- Just tycon -> match_tycon tycon
- Nothing -> match_fun
-
- match_tycon tycon inst_ty = case (getUniDataTyCon_maybe inst_ty) of
- Just (inst_tc,_,_) -> tycon == inst_tc
- Nothing -> False
-
- match_fun inst_ty = isFunType inst_ty
-
+ (name, loc, thing)
+ = case decl of
+ (ClassDecl _ name _ _ _ _ _ loc) -> (name, loc, "class")
+ (TySynonym name _ _ loc) -> (name, loc, "type synonym")
+ (TyData NewType _ name _ _ _ _ loc _ _) -> (name, loc, "newtype")
+ (TyData DataType _ name _ _ _ _ loc _ _) -> (name, loc, "data type")
+
+ ctxt = hsep [ptext SLIT("In the"), text thing,
+ ptext SLIT("declaration for"), quotes (ppr name)]
+\end{code}
-is_plain_instance inst_ty
- = case (getUniDataTyCon_maybe inst_ty) of
- Just (_,tys,_) -> all isTyVarTemplateTy tys
- Nothing -> case maybeUnpackFunTy inst_ty of
- Just (arg, res) -> isTyVarTemplateTy arg && isTyVarTemplateTy res
- Nothing -> error "TcInstDecls:is_plain_instance"
+\begin{code}
+instConstraintErr pred
+ = hang (ptext SLIT("Illegal constraint") <+>
+ quotes (pprPred pred) <+>
+ ptext SLIT("in instance context"))
+ 4 (ptext SLIT("(Instance contexts must constrain only type variables)"))
+
+badGenericInstanceType binds
+ = vcat [ptext SLIT("Illegal type pattern in the generic bindings"),
+ nest 4 (ppr binds)]
+
+missingGenericInstances missing
+ = ptext SLIT("Missing type patterns for") <+> pprQuotedList missing
+
+
+
+dupGenericInsts tc_inst_infos
+ = vcat [ptext SLIT("More than one type pattern for a single generic type constructor:"),
+ nest 4 (vcat (map ppr_inst_ty tc_inst_infos)),
+ ptext SLIT("All the type patterns for a generic type constructor must be identical")
+ ]
+ where
+ ppr_inst_ty (tc,inst) = ppr (simpleInstInfoTy inst)
+
+instTypeErr clas tys msg
+ = sep [ptext SLIT("Illegal instance declaration for") <+> quotes (pprConstraint clas tys),
+ nest 4 (parens msg)
+ ]
+
+nonBoxedPrimCCallErr clas inst_ty
+ = hang (ptext SLIT("Unacceptable instance type for ccall-ish class"))
+ 4 (hsep [ ptext SLIT("class"), ppr clas, ptext SLIT("type"),
+ ppr inst_ty])
+
+methodCtxt = ptext SLIT("When checking the methods of an instance declaration")
\end{code}
+
+