%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
%
\section[TcInstDecls]{Typechecking instance declarations}
#include "HsVersions.h"
module TcInstDcls (
- tcInstDecls1, tcInstDecls2,
- tcSpecInstSigs,
- buildInstanceEnvs, processInstBinds,
- mkInstanceRelatedIds,
- InstInfo(..)
+ tcInstDecls1,
+ tcInstDecls2,
+ tcMethodBind
) where
-IMPORT_Trace -- ToDo:rm debugging
-import Outputable
-import Pretty
-import TcMonad -- typechecking monad machinery
-import TcMonadFns ( newDicts, newMethod, newLocalWithGivenTy,
- newClassOpLocals, copyTyVars,
- applyTcSubstAndCollectTyVars
+IMP_Ubiq()
+
+import HsSyn ( HsDecl(..), InstDecl(..), TyDecl, ClassDecl, DefaultDecl,
+ FixityDecl, IfaceSig, Sig(..),
+ SpecInstSig(..), HsBinds(..),
+ MonoBinds(..), GRHSsAndBinds(..), GRHS(..), Match,
+ InPat(..), OutPat(..), HsExpr(..), HsLit(..),
+ Stmt, DoOrListComp, ArithSeqInfo, Fake, Fixity,
+ HsType(..), HsTyVar,
+ SYN_IE(RecFlag), recursive, nonRecursive, collectMonoBinders,
+ andMonoBinds
)
-import AbsSyn -- the stuff being typechecked
-
-import AbsUniType
-import BackSubst ( applyTcSubstToBinds )
-import Bag ( emptyBag, unitBag, unionBags, bagToList )
-import CE ( lookupCE, CE(..) )
-import CmdLineOpts ( GlobalSwitch(..) )
-import GenSpecEtc ( checkSigTyVars )
-import E ( mkE, getE_CE, getE_TCE, growE_LVE, tvOfE, LVE(..), E )
-import Errors ( dupInstErr, derivingWhenInstanceExistsErr,
- preludeInstanceErr, nonBoxedPrimCCallErr,
- specInstUnspecInstNotFoundErr,
- Error(..), UnifyErrContext(..)
+import RnHsSyn ( SYN_IE(RenamedHsBinds), SYN_IE(RenamedMonoBinds),
+ SYN_IE(RenamedInstDecl), SYN_IE(RenamedFixityDecl), SYN_IE(RenamedHsExpr),
+ SYN_IE(RenamedSig), SYN_IE(RenamedSpecInstSig), SYN_IE(RenamedHsDecl)
)
-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 LIE ( nullLIE, mkLIE, unMkLIE, plusLIE, LIE )
-import ListSetOps ( minusList )
-import TCE ( TCE(..), UniqFM )
-import TVE ( mkTVE, TVE(..) )
-import Spec ( specTy )
-import TcContext ( tcContext )
+import TcHsSyn ( TcIdOcc(..), SYN_IE(TcIdBndr), SYN_IE(TcHsBinds),
+ SYN_IE(TcMonoBinds), SYN_IE(TcExpr), tcIdType,
+ mkHsTyLam, mkHsTyApp,
+ mkHsDictLam, mkHsDictApp )
+
+import TcBinds ( tcBindWithSigs, tcPragmaSigs, TcSigInfo(..) )
+import TcMonad
+import RnMonad ( SYN_IE(RnNameSupply) )
+import Inst ( Inst, InstOrigin(..), SYN_IE(InstanceMapper),
+ instToId, newDicts, newMethod, SYN_IE(LIE), emptyLIE, plusLIE )
+import TcBinds ( tcPragmaSigs, checkSigTyVars )
+import PragmaInfo ( PragmaInfo(..) )
+import TcDeriv ( tcDeriving )
+import TcEnv ( tcLookupClass, newLocalId, tcExtendGlobalTyVars, tcGetGlobalTyVars )
+import SpecEnv ( SpecEnv )
import TcGRHSs ( tcGRHSsAndBinds )
+import TcInstUtil ( InstInfo(..), mkInstanceRelatedIds, buildInstanceEnvs )
+import TcKind ( TcKind, unifyKind )
import TcMatches ( tcMatchesFun )
-import TcMonoType ( tcInstanceType )
-import TcPragmas ( tcDictFunPragmas, tcGenPragmas )
-import TcSimplify ( tcSimplifyAndCheck, tcSimplifyThetas )
-import Unify ( unifyTauTy )
-import Unique ( cCallableClassKey, cReturnableClassKey )
-import Util
+import TcMonoType ( tcTyVarScope, tcContext, tcHsTypeKind )
+import TcSimplify ( tcSimplifyAndCheck )
+import TcType ( SYN_IE(TcType), SYN_IE(TcTyVar), SYN_IE(TcTyVarSet),
+ tcInstSigTyVars, tcInstType, tcInstSigTcType,
+ tcInstTheta, tcInstTcType, tcInstSigType
+ )
+import Unify ( unifyTauTy, unifyTauTyLists )
+
+
+import Bag ( emptyBag, unitBag, unionBags, unionManyBags,
+ concatBag, foldBag, bagToList, listToBag,
+ Bag )
+import CmdLineOpts ( opt_GlasgowExts, opt_CompilingGhcInternals,
+ opt_OmitDefaultInstanceMethods,
+ opt_SpecialiseOverloaded
+ )
+import Class ( GenClass, GenClassOp,
+ classBigSig, classOps, classOpLocalType,
+ classDefaultMethodId, SYN_IE(Class)
+ )
+import Id ( GenId, idType, isDefaultMethodId_maybe, replacePragmaInfo,
+ isNullaryDataCon, dataConArgTys, SYN_IE(Id) )
+import ListSetOps ( minusList )
+import Maybes ( maybeToBool, expectJust, seqMaybe )
+import Name ( nameOccName, getOccString, occNameString, moduleString,
+ isLocallyDefined, OccName, Name{--O only-}, SYN_IE(Module),
+ NamedThing(..)
+ )
+import PrelVals ( nO_EXPLICIT_METHOD_ERROR_ID )
+import PprType ( GenType, GenTyVar, GenClass, GenClassOp, TyCon,
+ pprParendGenType
+ )
+import Outputable
+import SrcLoc ( SrcLoc, noSrcLoc )
+import Pretty
+import TyCon ( isSynTyCon, isDataTyCon, derivedClasses )
+import Type ( GenType(..), SYN_IE(ThetaType), mkTyVarTys, isPrimType,
+ splitSigmaTy, splitAppTys, isTyVarTy, matchTy, mkSigmaTy,
+ getTyCon_maybe, maybeAppTyCon, SYN_IE(Type), getTyVar,
+ maybeBoxedPrimType, maybeAppDataTyCon, splitRhoTy, eqTy
+ )
+import TyVar ( GenTyVar, SYN_IE(GenTyVarSet), tyVarSetToList,
+ mkTyVarSet, unionTyVarSets, SYN_IE(TyVar) )
+import TysPrim ( byteArrayPrimTyCon, mutableByteArrayPrimTyCon )
+import TysWiredIn ( stringTy )
+import Unique ( Unique, cCallableClassKey, cReturnableClassKey, Uniquable(..) )
+import Util ( zipEqual, panic, pprPanic, pprTrace, removeDups, Ord3(..),
+#if __GLASGOW_HASKELL__ < 202
+ , trace
+#endif
+ )
\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 specilaised instances
-\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
\end{enumerate}
\begin{code}
-tcInstDecls1 :: E -> CE -> TCE -> [RenamedInstDecl] -> NF_TcM (Bag InstInfo)
-
-tcInstDecls1 e ce tce [] = returnNF_Tc emptyBag
-
-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)
- 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 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}
-
-
-Common bit of code shared with @tcDeriving@:
-\begin{code}
-mkInstanceRelatedIds e
- from_here 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)
-
-
- dfun_theta = case inst_decl_theta of
-
- [] -> [] -- If inst_decl_theta is empty, then we don't
- -- want to have any dict arguments, so that we can
- -- expose the constant methods.
-
- other -> inst_decl_theta ++ super_class_theta
- -- Otherwise we pass the superclass dictionaries to
- -- the dictionary function; the Mark Jones optimisation.
+tcInstDecls1 :: [RenamedHsDecl]
+ -> Module -- module name for deriving
+ -> RnNameSupply -- for renaming derivings
+ -> TcM s (Bag InstInfo,
+ RenamedHsBinds,
+ PprStyle -> Doc)
+
+tcInstDecls1 decls mod_name rn_name_supply
+ = -- Do the ordinary instance declarations
+ mapNF_Tc (tcInstDecl1 mod_name)
+ [inst_decl | InstD inst_decl <- decls] `thenNF_Tc` \ inst_info_bags ->
+ let
+ decl_inst_info = unionManyBags inst_info_bags
+ in
+ -- Handle "derived" instances; note that we only do derivings
+ -- for things in this module; we ignore deriving decls from
+ -- interfaces! We pass fixities, because they may be used
+ -- in deriving Read and Show.
+ tcDeriving mod_name rn_name_supply decl_inst_info
+ `thenTc` \ (deriv_inst_info, deriv_binds, ddump_deriv) ->
- dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_ty)
+ let
+ full_inst_info = deriv_inst_info `unionBags` decl_inst_info
in
- fixNF_Tc ( \ rec_dfun_id ->
- babyTcMtoNF_TcM (
- tcDictFunPragmas e dfun_ty rec_dfun_id inst_pragmas
- ) `thenNF_Tc` \ dfun_id_info ->
-
- returnNF_Tc (mkDictFunId uniq clas inst_ty dfun_ty from_here dfun_id_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 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 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)
-\end{code}
+ returnTc (full_inst_info, deriv_binds, ddump_deriv)
-%************************************************************************
-%* *
-\subsection{Converting instance info into suitable InstEnvs}
-%* *
-%************************************************************************
+tcInstDecl1 :: Module -> RenamedInstDecl -> NF_TcM s (Bag InstInfo)
-\begin{code}
-buildInstanceEnvs :: Bag InstInfo
- -> TcM InstanceMapper
+tcInstDecl1 mod_name (InstDecl poly_ty binds uprags (Just dfun_name) src_loc)
+ = -- Prime error recovery, set source location
+ recoverNF_Tc (returnNF_Tc emptyBag) $
+ tcAddSrcLoc src_loc $
-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_
+ -- Look things up
+ tcLookupClass class_name `thenTc` \ (clas_kind, clas) ->
- 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}
+ -- Typecheck the context and instance type
+ tcTyVarScope tyvar_names (\ tyvars ->
+ tcContext context `thenTc` \ theta ->
+ tcHsTypeKind inst_ty `thenTc` \ (tau_kind, tau) ->
+ unifyKind clas_kind tau_kind `thenTc_`
+ returnTc (tyvars, theta, tau)
+ ) `thenTc` \ (inst_tyvars, inst_theta, inst_tau) ->
-\begin{code}
-buildInstanceEnv :: [InstInfo] -- Non-empty, and all for same class
- -> TcM (Class, (ClassInstEnv, (ClassOp -> SpecEnv)))
+ -- Check for respectable instance type
+ scrutiniseInstanceType dfun_name clas inst_tau
+ `thenTc` \ (inst_tycon,arg_tys) ->
-buildInstanceEnv inst_infos@(info_for_one@(InstInfo clas _ _ _ _ _ _ _ _ _ _ _) : rest)
- = let
- ops = getClassOps clas
- no_of_ops = length ops
- in
- foldlTc addClassInstance
- (nullMEnv, nOfThem no_of_ops nullSpecEnv)
- inst_infos `thenTc` \ (class_inst_env, op_inst_envs) ->
- 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
- in
- returnTc (clas, (class_inst_env, class_op_fn))
-\end{code}
+ -- Make the dfun id and constant-method ids
+ mkInstanceRelatedIds dfun_name
+ clas inst_tyvars inst_tau inst_theta
+ `thenNF_Tc` \ (dfun_id, dfun_theta) ->
-\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 _)
- = -- 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')
+ returnTc (unitBag (InstInfo clas inst_tyvars inst_tau inst_theta
+ dfun_theta dfun_id
+ binds src_loc uprags))
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.
+ (tyvar_names, context, dict_ty) = case poly_ty of
+ HsForAllTy tvs cxt dict_ty -> (tvs, cxt, dict_ty)
+ other -> ([], [], poly_ty)
+ (class_name, inst_ty) = case dict_ty of
+ MonoDictTy cls ty -> (cls,ty)
+ other -> pprPanic "Malformed instance decl" (ppr PprDebug poly_ty)
\end{code}
%************************************************************************
\begin{code}
-tcInstDecls2 :: E
- -> Bag InstInfo
- -> NF_TcM (LIE, TypecheckedBinds)
-
-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 :: Bag InstInfo
+ -> NF_TcM s (LIE s, TcHsBinds s)
-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, EmptyBinds)) inst_decls
+ where
+ combine tc1 tc2 = tc1 `thenNF_Tc` \ (lie1, binds1) ->
+ tc2 `thenNF_Tc` \ (lie2, binds2) ->
+ returnNF_Tc (lie1 `plusLIE` lie2,
+ binds1 `ThenBinds` 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.
+First comes the easy case of a non-local instance decl.
+
\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-} _ locn _)
- = let
- origin = InstanceDeclOrigin locn
- in
- recoverTc (nullLIE, EmptyBinds) (
- addSrcLocTc locn (
- pruneSubstTc free_tyvars (
+tcInstDecl2 :: InstInfo -> NF_TcM s (LIE s, TcHsBinds s)
+
+tcInstDecl2 (InstInfo clas inst_tyvars inst_ty
+ inst_decl_theta dfun_theta
+ dfun_id monobinds
+ locn uprags)
+ | not (isLocallyDefined dfun_id)
+ = returnNF_Tc (emptyLIE, EmptyBinds)
+
+{-
+ -- I deleted this "optimisation" because when importing these
+ -- instance decls the renamer would look for the dfun bindings and they weren't there.
+ -- This would be fixable, but it seems simpler just to produce a tiny void binding instead,
+ -- even though it's never used.
+
+ -- This case deals with CCallable etc, which don't need any bindings
+ | isNoDictClass clas
+ = returnNF_Tc (emptyLIE, EmptyBinds)
+-}
+
+ | otherwise
+ = -- Prime error recovery
+ recoverNF_Tc (returnNF_Tc (emptyLIE, EmptyBinds)) $
+ tcAddSrcLoc locn $
-- 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) ->
+ tcInstSigTyVars inst_tyvars `thenNF_Tc` \ (inst_tyvars', _, tenv) ->
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)
+ origin = InstanceDeclOrigin
+ (class_tyvar,
+ super_classes, sc_sel_ids,
+ class_ops, op_sel_ids, defm_ids) = classBigSig clas
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' ->
+ tcInstType tenv inst_ty `thenNF_Tc` \ inst_ty' ->
+ tcInstTheta tenv dfun_theta `thenNF_Tc` \ dfun_theta' ->
+ tcInstTheta tenv inst_decl_theta `thenNF_Tc` \ inst_decl_theta' ->
let
- sc_dicts'_ids = map mkInstId sc_dicts'
- dfun_arg_dicts'_ids = map mkInstId dfun_arg_dicts'
+ sc_theta' = super_classes `zip` repeat inst_ty'
in
- -- Instantiate the dictionary being constructed
- -- and the dictionary-construction function
- newDicts origin [(clas,inst_ty)] `thenNF_Tc` \ [this_dict] ->
+ -- Create dictionary Ids from the specified instance contexts.
+ newDicts origin sc_theta' `thenNF_Tc` \ (sc_dicts, sc_dict_ids) ->
+ newDicts origin dfun_theta' `thenNF_Tc` \ (dfun_arg_dicts, dfun_arg_dicts_ids) ->
+ newDicts origin inst_decl_theta' `thenNF_Tc` \ (inst_decl_dicts, _) ->
+ newDicts origin [(clas,inst_ty')] `thenNF_Tc` \ (this_dict, [this_dict_id]) ->
+
+ -- Now process any INLINE or SPECIALIZE pragmas for the methods
+ -- ...[NB May 97; all ignored except INLINE]
+ tcPragmaSigs uprags `thenTc` \ (prag_fn, spec_binds, spec_lie) ->
+
+ -- Check the method bindings
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
- processInstBinds e free_tyvars
- (makeInstanceDeclDefaultMethodExpr origin this_dict_id class_ops defm_ids inst_ty)
- inst_tyvars avail_insts method_ids monobinds
- `thenTc` \ (insts_needed, method_mbinds) ->
- -- Complete the binding group
- let this_dict_bind
- = VarMonoBind this_dict_id (Dictionary sc_dicts'_ids method_ids)
- dict_and_method_binds
- = this_dict_bind `AndMonoBinds` method_mbinds
+ inst_tyvars_set' = mkTyVarSet inst_tyvars'
+ check_from_this_class (bndr, loc)
+ | nameOccName bndr `elem` sel_names = returnTc ()
+ | otherwise = recoverTc (returnTc ()) $
+ tcAddSrcLoc loc $
+ failTc (instBndrErr bndr clas)
+ sel_names = map getOccName op_sel_ids
in
+ mapTc check_from_this_class (bagToList (collectMonoBinders monobinds)) `thenTc_`
+ tcExtendGlobalTyVars inst_tyvars_set' (
+ mapAndUnzip3Tc (tcMethodBind (getDefmRhs clas) inst_ty' prag_fn monobinds)
+ (op_sel_ids `zip` [0..])
+ ) `thenTc` \ (method_binds_s, insts_needed_s, meth_lies_w_ids) ->
+
-- 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
+ let
+ (meth_lies, meth_ids) = unzip meth_lies_w_ids
+ avail_insts -- These insts are in scope; quite a few, eh?
+ = this_dict `plusLIE` dfun_arg_dicts `plusLIE` unionManyBags meth_lies
+ in
+ tcAddErrCtxt bindSigCtxt (
+ tcSimplifyAndCheck
+ inst_tyvars_set' -- Local tyvars
avail_insts
- (sc_dicts' ++ insts_needed) -- Need to get defns for all these
- (BindSigCtxt method_ids)
- `thenTc` \ (const_insts, super_binds) ->
+ (sc_dicts `unionBags`
+ unionManyBags insts_needed_s) -- Need to get defns for all these
+ ) `thenTc` \ (const_lie, 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_`
+ tcAddErrCtxt superClassSigCtxt (
+ tcSimplifyAndCheck
+ inst_tyvars_set' -- Local tyvars
+ inst_decl_dicts -- The instance dictionaries available
+ sc_dicts -- The superclass dicationaries reqd
+ ) `thenTc_`
-- Ignore the result; we're only doing
-- this to make sure it can be done.
-
- -- Create the dictionary function binding itself
- let 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)
- in
-
- -- Back-substitute
- applyTcSubstToBinds inst_binds `thenNF_Tc` \ final_inst_binds ->
-
- returnTc (mkLIE const_insts, final_inst_binds)
- )))
-\end{code}
-
-@mkMethodId@ manufactures an id for a local method.
-It's rather turgid stuff, because there are two cases:
-
- (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.
-
- (b) For methods with local polymorphism, we can't do this. For example,
-
- class Foo a where
- op :: (Num b) => a -> b -> a
-
- Here the type of the class-op-selector is
-
- forall a b. (Foo a, Num b) => a -> b -> a
-
- The locally defined method at (say) type Float will have type
-
- forall b. (Num b) => Float -> b -> Float
- and the one is not an instance of the other.
-
- So for these we just make a local (non-Inst) id with a suitable type.
-
-How disgusting.
-
-\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)
+ -- Create the result bindings
+ let
+ dict_bind = VarMonoBind this_dict_id (Dictionary sc_dict_ids meth_ids)
+ method_binds = andMonoBinds method_binds_s
+
+ main_bind
+ = MonoBind (
+ AbsBinds
+ inst_tyvars'
+ dfun_arg_dicts_ids
+ [(inst_tyvars', RealId dfun_id, this_dict_id)]
+ (super_binds `AndMonoBinds`
+ method_binds `AndMonoBinds`
+ dict_bind))
+ [] recursive -- Recursive to play safe
+ in
+ returnTc (const_lie `plusLIE` spec_lie,
+ main_bind `ThenBinds` spec_binds)
\end{code}
-This function makes a default method which calls the global default method, at
-the appropriate instance type.
+The next function looks for a method binding; if there isn't one it
+manufactures one that just calls the global default method.
See the notes under default decls in TcClassDcl.lhs.
\begin{code}
-makeInstanceDeclDefaultMethodExpr
- :: InstOrigin
- -> Id
- -> [ClassOp]
- -> [Id]
- -> UniType
- -> Int
- -> NF_TcM TypecheckedExpr
-
-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 ->
- let
- local_dicts = map mkInstId local_dict_insts
- 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
+getDefmRhs :: Class -> Int -> RenamedHsExpr
+getDefmRhs clas idx = HsVar (getName (classDefaultMethodId clas idx))
\end{code}
%* *
%************************************************************************
-@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
-
- -> [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 ->
-
- returnTc (insts_needed_in_methods,
- method_binds `AndMonoBinds` default_monobinds)
- ))
-\end{code}
-
\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}
-
-\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.
+tcMethodBind
+ :: (Int -> RenamedHsExpr) -- Function mapping a tag to default RHS
+ -> TcType s -- Instance type
+ -> (Name -> PragmaInfo)
+ -> RenamedMonoBinds -- Method binding
+ -> (Id, Int) -- Selector ID (and its 0-indexed tag)
+ -- for which binding is wanted
+ -> TcM s (TcMonoBinds s, LIE s, (LIE s, TcIdOcc s))
+
+tcMethodBind deflt_fn inst_ty prag_fn meth_binds (sel_id, idx)
+ = newMethod origin (RealId sel_id) [inst_ty] `thenNF_Tc` \ meth@(_, TcId meth_id) ->
+ tcInstSigTcType (idType meth_id) `thenNF_Tc` \ (tyvars', rho_ty') ->
let
- (op,locn) = case mbind of
- FunMonoBind op _ locn -> (op, locn)
- PatMonoBind (VarPatIn op) _ locn -> (op, locn)
-
- origin = InstanceDeclOrigin locn
- in
- addSrcLocTc locn (
-
- -- Make a method id for the method
- let tag = getTagFromClassOpName op
- method_id = method_ids !! (tag-1)
- method_ty = getIdUniType method_id
+ meth_name = getName meth_id
+ default_bind = PatMonoBind (VarPatIn meth_name)
+ (GRHSsAndBindsIn [OtherwiseGRHS (deflt_fn idx) noSrcLoc] EmptyBinds)
+ noSrcLoc
+
+ (op_name, op_bind) = case go (getOccName sel_id) meth_binds of
+ Just stuff -> stuff
+ Nothing -> (meth_name, default_bind)
+
+ (theta', tau') = splitRhoTy rho_ty'
+ meth_id_w_prags = replacePragmaInfo meth_id (prag_fn meth_name)
+ sig_info = TySigInfo op_name meth_id_w_prags tyvars' theta' tau' noSrcLoc
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}
+ tcBindWithSigs [op_name] op_bind [sig_info]
+ nonRecursive (\_ -> NoPragmaInfo) `thenTc` \ (binds, insts, _) ->
-\begin{code}
-tcMethodBind :: E -> Id -> UniType -> RenamedMonoBinds
- -> TcM (TypecheckedMonoBinds, LIE)
+ returnTc (binds, insts, meth)
+ where
+ origin = InstanceDeclOrigin -- Poor
-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)
- )
+ go occ EmptyMonoBinds = Nothing
+ go occ (AndMonoBinds b1 b2) = go occ b1 `seqMaybe` go occ b2
-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)
- )
+ go occ b@(FunMonoBind op_name _ _ locn) | nameOccName op_name == occ = Just (op_name, b)
+ | otherwise = Nothing
+ go occ b@(PatMonoBind (VarPatIn op_name) _ locn) | nameOccName op_name == occ = Just (op_name, b)
+ | otherwise = Nothing
+ go occ other = panic "Urk! Bad instance method binding"
\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}
%************************************************************************
%* *
%************************************************************************
\begin{code}
+{- LATER
tcSpecInstSigs :: E -> CE -> TCE
- -> Bag InstInfo -- inst decls seen (declared and derived)
- -> [RenamedSpecialisedInstanceSig] -- specialise instance upragmas
- -> TcM (Bag InstInfo) -- new, overlapped, inst decls
+ -> Bag InstInfo -- inst decls seen (declared and derived)
+ -> [RenamedSpecInstSig] -- specialise instance upragmas
+ -> TcM (Bag InstInfo) -- new, overlapped, inst decls
tcSpecInstSigs e ce tce inst_infos []
= returnTc emptyBag
= 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)
+ 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
+ -> RenamedSpecInstSig
-> NF_TcM (Bag InstInfo)
-tcSpecInstSig e ce tce inst_infos inst_mapper (InstSpecSig class_name ty src_loc)
+tcSpecInstSig e ce tce inst_infos inst_mapper (SpecInstSig class_name ty src_loc)
= recoverTc emptyBag (
- addSrcLocTc src_loc (
+ tcAddSrcLoc 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
+ ty_names = extractHsTyNames ???is_tyvarish_name??? 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
- tycon = case getUniDataTyCon_maybe inst_ty of
- Just (tc,_,_) -> tc
- Nothing -> panic "tcSpecInstSig:inst_tycon"
+ maybe_tycon = case maybeAppDataTyCon inst_ty of
+ Just (tc,_,_) -> Just tc
+ Nothing -> Nothing
- maybe_unspec_inst = lookup_unspec_inst clas tycon inst_infos
+ 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
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
+ _ _ binds _ 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
+ subst_tv_theta = instantiateThetaTy tv_e subst_theta
mk_spec_origin clas ty
- = InstanceSpecOrigin inst_mapper clas ty src_loc
+ = InstanceSpecOrigin inst_mapper clas ty src_loc
+ -- I'm VERY SUSPICIOUS ABOUT THIS
+ -- the inst-mapper is in a knot at this point so it's no good
+ -- looking at it in tcSimplify...
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_tmpl_map = zipEqual "tcSpecInstSig" inst_tv_tys inst_tmpl_tys
tv_to_tmpl tv = assoc "tcSpecInstSig" tv_tmpl_map tv
in
- mkInstanceRelatedIds e True{-from here-} NoInstancePragmas src_loc
+ mkInstanceRelatedIds
clas inst_tmpls inst_ty simpl_theta uprag
- `thenTc` \ (dfun_id, dfun_theta, const_meth_ids) ->
+ `thenNF_Tc` \ (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) (
+ (vcat [hsep [if null simpl_theta then empty else ppr PprDebug simpl_theta,
+ if null simpl_theta then empty else ptext SLIT("=>"),
+ ppr PprDebug clas,
+ pprParendGenType PprDebug inst_ty],
+ hsep [ptext SLIT(" derived from:"),
+ if null unspec_theta then empty else ppr PprDebug unspec_theta,
+ if null unspec_theta then empty else ptext SLIT("=>"),
+ ppr PprDebug clas,
+ pprParendGenType 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))
+ dfun_theta dfun_id
+ binds src_loc uprag))
)))
-lookup_unspec_inst clas tycon inst_infos
- = case filter match_info (bagToList inst_infos) of
+lookup_unspec_inst clas maybe_tycon inst_infos
+ = case filter (match_info match_inst_ty) (bagToList inst_infos) of
[] -> Nothing
(info:_) -> Just info
where
- match_info (InstInfo inst_clas _ inst_ty _ _ _ _ _ from_here _ _ _)
- = from_here && clas == inst_clas && inst_ty_matches_tycon
- where
- inst_ty_matches_tycon = case (getUniDataTyCon_maybe inst_ty) of
- Just (inst_tc,tys,_) -> tycon == inst_tc && all isTyVarTemplateTy tys
- Nothing -> False
+ 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 (maybeAppDataTyCon inst_ty) of
+ Just (inst_tc,_,_) -> tycon == inst_tc
+ Nothing -> False
+
+ match_fun inst_ty = isFunType inst_ty
+
+
+is_plain_instance inst_ty
+ = case (maybeAppDataTyCon 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"
+-}
+\end{code}
+
+
+Checking for a decent instance type
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+@scrutiniseInstanceType@ checks the type {\em and} its syntactic constraints:
+it must normally look like: @instance Foo (Tycon a b c ...) ...@
+
+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.
+
+We can also have instances for functions: @instance Foo (a -> b) ...@.
+
+\begin{code}
+scrutiniseInstanceType dfun_name clas inst_tau
+ -- TYCON CHECK
+ | not (maybeToBool inst_tycon_maybe) || isSynTyCon inst_tycon
+ = failTc (instTypeErr inst_tau)
+
+ -- IMPORTED INSTANCES ARE OK (but see tcInstDecl1)
+ | not (isLocallyDefined dfun_name)
+ = returnTc (inst_tycon,arg_tys)
+
+ -- TYVARS CHECK
+ | not (opt_GlasgowExts ||
+ (all isTyVarTy arg_tys && null tyvar_dups)
+ )
+ = failTc (instTypeErr inst_tau)
+
+ -- DERIVING CHECK
+ -- It is obviously illegal to have an explicit instance
+ -- for something that we are also planning to `derive'
+ -- Though we can have an explicit instance which is more
+ -- specific than the derived instance
+ | clas `elem` (derivedClasses inst_tycon)
+ && all isTyVarTy arg_tys
+ = failTc (derivingWhenInstanceExistsErr clas inst_tycon)
+
+ | -- CCALL CHECK
+ -- A user declaration of a CCallable/CReturnable instance
+ -- must be for a "boxed primitive" type.
+ (uniqueOf clas == cCallableClassKey && not (ccallable_type inst_tau)) ||
+ (uniqueOf clas == cReturnableClassKey && not (creturnable_type inst_tau))
+ = failTc (nonBoxedPrimCCallErr clas inst_tau)
+
+ | otherwise
+ = returnTc (inst_tycon,arg_tys)
+
+ where
+ (possible_tycon, arg_tys) = splitAppTys inst_tau
+ inst_tycon_maybe = getTyCon_maybe possible_tycon
+ inst_tycon = expectJust "tcInstDecls1:inst_tycon" inst_tycon_maybe
+ (_, tyvar_dups) = removeDups cmp (map (getTyVar "tcInstDecls1:getTyVarTy") arg_tys)
+
+-- These conditions come directly from what the DsCCall is capable of.
+-- Totally grotesque. Green card should solve this.
+
+ccallable_type ty = isPrimType ty || -- Allow CCallable Int# etc
+ maybeToBool (maybeBoxedPrimType ty) || -- Ditto Int etc
+ ty `eqTy` stringTy ||
+ byte_arr_thing
+ where
+ byte_arr_thing = case maybeAppDataTyCon ty of
+ Just (tycon, ty_args, [data_con]) | isDataTyCon tycon ->
+ length data_con_arg_tys == 2 &&
+ maybeToBool maybe_arg2_tycon &&
+ (arg2_tycon == byteArrayPrimTyCon ||
+ arg2_tycon == mutableByteArrayPrimTyCon)
+ where
+ data_con_arg_tys = dataConArgTys data_con ty_args
+ (data_con_arg_ty1 : data_con_arg_ty2 : _) = data_con_arg_tys
+ maybe_arg2_tycon = maybeAppTyCon data_con_arg_ty2
+ Just (arg2_tycon,_) = maybe_arg2_tycon
+
+ other -> False
+
+creturnable_type ty = maybeToBool (maybeBoxedPrimType ty) ||
+ -- Or, a data type with a single nullary constructor
+ case (maybeAppDataTyCon ty) of
+ Just (tycon, tys_applied, [data_con])
+ -> isNullaryDataCon data_con
+ other -> False
+\end{code}
+
+\begin{code}
+
+instTypeErr ty sty
+ = case ty of
+ SynTy tc _ _ -> hsep [ptext SLIT("The type synonym"), ppr sty tc, rest_of_msg]
+ TyVarTy tv -> hsep [ptext SLIT("The type variable"), ppr sty tv, rest_of_msg]
+ other -> hsep [ptext SLIT("The type"), ppr sty ty, rest_of_msg]
+ where
+ rest_of_msg = ptext SLIT("cannot be used as an instance type")
+
+instBndrErr bndr clas sty
+ = hsep [ptext SLIT("Class"), ppr sty clas, ptext SLIT("does not have a method"), ppr sty bndr]
+
+derivingWhenInstanceExistsErr clas tycon sty
+ = hang (hsep [ptext SLIT("Deriving class"),
+ ppr sty clas,
+ ptext SLIT("type"), ppr sty tycon])
+ 4 (ptext SLIT("when an explicit instance exists"))
+
+derivingWhenInstanceImportedErr inst_mod clas tycon sty
+ = hang (hsep [ptext SLIT("Deriving class"),
+ ppr sty clas,
+ ptext SLIT("type"), ppr sty tycon])
+ 4 (hsep [ptext SLIT("when an instance declared in module"),
+ pp_mod, ptext SLIT("has been imported")])
+ where
+ pp_mod = hsep [ptext SLIT("module"), ptext inst_mod]
+
+nonBoxedPrimCCallErr clas inst_ty sty
+ = hang (ptext SLIT("Unacceptable instance type for ccall-ish class"))
+ 4 (hsep [ ptext SLIT("class"), ppr sty clas, ptext SLIT("type"),
+ ppr sty inst_ty])
+
+omitDefaultMethodWarn clas_op clas_name inst_ty sty
+ = hsep [ptext SLIT("Warning: Omitted default method for"),
+ ppr sty clas_op, ptext SLIT("in instance"),
+ text clas_name, pprParendGenType sty inst_ty]
+
+instMethodNotInClassErr occ clas sty
+ = hang (ptext SLIT("Instance mentions a method not in the class"))
+ 4 (hsep [ptext SLIT("class"), ppr sty clas, ptext SLIT("method"),
+ ppr sty occ])
+
+patMonoBindsCtxt pbind sty
+ = hang (ptext SLIT("In a pattern binding:"))
+ 4 (ppr sty pbind)
+
+methodSigCtxt name ty sty
+ = hang (hsep [ptext SLIT("When matching the definition of class method"),
+ ppr sty name, ptext SLIT("to its signature :") ])
+ 4 (ppr sty ty)
+
+bindSigCtxt sty
+ = ptext SLIT("When checking methods of an instance declaration")
+
+superClassSigCtxt sty
+ = ptext SLIT("When checking superclass constraints of an instance declaration")
\end{code}