Inst,
pprInst, pprInsts, pprInstsInFull, tidyInsts, tidyMoreInsts,
- newDictsFromOld, newDicts,
- newMethod, newMethodWithGivenTy, newOverloadedLit,
- newIPDict, tcInstId,
+ newDictsFromOld, newDicts, cloneDict,
+ newMethod, newMethodWithGivenTy, newMethodAtLoc,
+ newOverloadedLit, newIPDict, tcInstCall,
tyVarsOfInst, tyVarsOfInsts, tyVarsOfLIE,
ipNamesOfInst, ipNamesOfInsts, predsOfInst, predsOfInsts,
- instLoc, getDictClassTys,
+ instLoc, getDictClassTys, dictPred,
lookupInst, lookupSimpleInst, LookupInstResult(..),
isDict, isClassDict, isMethod,
+ isLinearInst, linearInstType,
isTyVarDict, isStdClassTyVarDict, isMethodFor,
instBindingRequired, instCanBeGeneralised,
#include "HsVersions.h"
-import CmdLineOpts ( opt_NoMethodSharing )
import HsSyn ( HsLit(..), HsOverLit(..), HsExpr(..) )
-import TcHsSyn ( TcExpr, TcId,
+import TcHsSyn ( TcExpr, TcId, TypecheckedHsExpr,
mkHsTyApp, mkHsDictApp, mkHsConApp, zonkId
)
import TcMonad
isIntTy,isFloatTy, isIntegerTy, isDoubleTy,
tcIsTyVarTy, mkPredTy, mkTyVarTy, mkTyVarTys,
tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tidyPred,
- isClassPred, isTyVarClassPred,
+ isClassPred, isTyVarClassPred, isLinearPred,
getClassPredTys, getClassPredTys_maybe, mkPredName,
tidyType, tidyTypes, tidyFreeTyVars,
tcCmpType, tcCmpTypes, tcCmpPred
)
import CoreFVs ( idFreeTyVars )
import Class ( Class )
-import Id ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId )
+import Id ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId, setIdUnique )
import PrelInfo ( isStandardClass, isCcallishClass, isNoDictClass )
import Name ( Name, mkMethodOcc, getOccName )
-import NameSet ( NameSet )
-import PprType ( pprPred )
+import PprType ( pprPred, pprParendType )
import Subst ( emptyInScopeSet, mkSubst,
substTy, substTyWith, substTheta, mkTyVarSubst, mkTopTyVarSubst
)
import TysWiredIn ( floatDataCon, doubleDataCon )
import PrelNames( fromIntegerName, fromRationalName )
import Util ( thenCmp, equalLength )
+import BasicTypes( IPName(..), mapIPName, ipNameName )
+
import Bag
import Outputable
\end{code}
instLoc (Method _ _ _ _ _ loc) = loc
instLoc (LitInst _ _ _ loc) = loc
+dictPred (Dict _ pred _ ) = pred
+dictPred inst = pprPanic "dictPred" (ppr inst)
+
getDictClassTys (Dict _ pred _) = getClassPredTys pred
predsOfInsts :: [Inst] -> [PredType]
ipNamesOfInsts :: [Inst] -> [Name]
ipNamesOfInst :: Inst -> [Name]
-- Get the implicit parameters mentioned by these Insts
+-- NB: ?x and %x get different Names
ipNamesOfInsts insts = [n | inst <- insts, n <- ipNamesOfInst inst]
-ipNamesOfInst (Dict _ (IParam n _) _) = [n]
-ipNamesOfInst (Method _ _ _ theta _ _) = [n | IParam n _ <- theta]
+ipNamesOfInst (Dict _ (IParam n _) _) = [ipNameName n]
+ipNamesOfInst (Method _ _ _ theta _ _) = [ipNameName n | IParam n _ <- theta]
ipNamesOfInst other = []
tyVarsOfInst :: Inst -> TcTyVarSet
isMethodFor ids (Method uniq id tys _ _ loc) = id `elemVarSet` ids
isMethodFor ids inst = False
+isLinearInst :: Inst -> Bool
+isLinearInst (Dict _ pred _) = isLinearPred pred
+isLinearInst other = False
+ -- We never build Method Insts that have
+ -- linear implicit paramters in them.
+ -- Hence no need to look for Methods
+ -- See TcExpr.tcId
+
+linearInstType :: Inst -> TcType -- %x::t --> t
+linearInstType (Dict _ (IParam _ ty) _) = ty
+
+
isStdClassTyVarDict (Dict _ pred _) = case getClassPredTys_maybe pred of
Just (clas, [ty]) -> isStandardClass clas && tcIsTyVarTy ty
other -> False
\begin{code}
instBindingRequired :: Inst -> Bool
instBindingRequired (Dict _ (ClassP clas _) _) = not (isNoDictClass clas)
-instBindingRequired (Dict _ (IParam _ _) _) = False
instBindingRequired other = True
instCanBeGeneralised :: Inst -> Bool
= tcGetInstLoc orig `thenNF_Tc` \ loc ->
newDictsAtLoc loc theta
+cloneDict :: Inst -> NF_TcM Inst
+cloneDict (Dict id ty loc) = tcGetUnique `thenNF_Tc` \ uniq ->
+ returnNF_Tc (Dict (setIdUnique id uniq) ty loc)
+
newDictsFromOld :: Inst -> TcThetaType -> NF_TcM [Inst]
newDictsFromOld (Dict _ _ loc) theta = newDictsAtLoc loc theta
where
mk_dict uniq pred = Dict (mkLocalId (mkPredName uniq loc pred) (mkPredTy pred)) pred inst_loc
--- For implicit parameters, since there is only one in scope
--- at any time, we use the name of the implicit parameter itself
-newIPDict orig name ty
- = tcGetInstLoc orig `thenNF_Tc` \ inst_loc ->
- returnNF_Tc (Dict (mkLocalId name (mkPredTy pred)) pred inst_loc)
- where pred = IParam name ty
+-- For vanilla implicit parameters, there is only one in scope
+-- at any time, so we used to use the name of the implicit parameter itself
+-- But with splittable implicit parameters there may be many in
+-- scope, so we make up a new name.
+newIPDict :: InstOrigin -> IPName Name -> Type
+ -> NF_TcM (IPName Id, Inst)
+newIPDict orig ip_name ty
+ = tcGetInstLoc orig `thenNF_Tc` \ inst_loc@(_,loc,_) ->
+ tcGetUnique `thenNF_Tc` \ uniq ->
+ let
+ pred = IParam ip_name ty
+ id = mkLocalId (mkPredName uniq loc pred) (mkPredTy pred)
+ in
+ returnNF_Tc (mapIPName (\n -> id) ip_name, Dict id pred inst_loc)
\end{code}
%* *
%************************************************************************
-tcInstId instantiates an occurrence of an Id.
-The instantiate_it loop runs round instantiating the Id.
-It has to be a loop because we are now prepared to entertain
-types like
- f:: forall a. Eq a => forall b. Baz b => tau
-We want to instantiate this to
- f2::tau {f2 = f1 b (Baz b), f1 = f a (Eq a)}
-
-The -fno-method-sharing flag controls what happens so far as the LIE
-is concerned. The default case is that for an overloaded function we
-generate a "method" Id, and add the Method Inst to the LIE. So you get
-something like
- f :: Num a => a -> a
- f = /\a (d:Num a) -> let m = (+) a d in \ (x:a) -> m x x
-If you specify -fno-method-sharing, the dictionary application
-isn't shared, so we get
- f :: Num a => a -> a
- f = /\a (d:Num a) (x:a) -> (+) a d x x
-This gets a bit less sharing, but
- a) it's better for RULEs involving overloaded functions
- b) perhaps fewer separated lambdas
-
\begin{code}
-tcInstId :: Id -> NF_TcM (TcExpr, LIE, TcType)
-tcInstId fun
- | opt_NoMethodSharing = loop_noshare (HsVar fun) (idType fun)
- | otherwise = loop_share fun
- where
- orig = OccurrenceOf fun
- loop_noshare fun fun_ty
- = tcInstType fun_ty `thenNF_Tc` \ (tyvars, theta, tau) ->
- let
- ty_app = mkHsTyApp fun (mkTyVarTys tyvars)
- in
- if null theta then -- Is it overloaded?
- returnNF_Tc (ty_app, emptyLIE, tau)
- else
- newDicts orig theta `thenNF_Tc` \ dicts ->
- loop_noshare (mkHsDictApp ty_app (map instToId dicts)) tau `thenNF_Tc` \ (expr, lie, final_tau) ->
- returnNF_Tc (expr, mkLIE dicts `plusLIE` lie, final_tau)
-
- loop_share fun
- = tcInstType (idType fun) `thenNF_Tc` \ (tyvars, theta, tau) ->
- let
- arg_tys = mkTyVarTys tyvars
- in
- if null theta then -- Is it overloaded?
- returnNF_Tc (mkHsTyApp (HsVar fun) arg_tys, emptyLIE, tau)
- else
- -- Yes, it's overloaded
- newMethodWithGivenTy orig fun arg_tys theta tau `thenNF_Tc` \ meth ->
- loop_share (instToId meth) `thenNF_Tc` \ (expr, lie, final_tau) ->
- returnNF_Tc (expr, unitLIE meth `plusLIE` lie, final_tau)
-
+tcInstCall :: InstOrigin -> TcType -> NF_TcM (TypecheckedHsExpr -> TypecheckedHsExpr, LIE, TcType)
+tcInstCall orig fun_ty -- fun_ty is usually a sigma-type
+ = tcInstType fun_ty `thenNF_Tc` \ (tyvars, theta, tau) ->
+ newDicts orig theta `thenNF_Tc` \ dicts ->
+ let
+ inst_fn e = mkHsDictApp (mkHsTyApp e (mkTyVarTys tyvars)) (map instToId dicts)
+ in
+ returnNF_Tc (inst_fn, mkLIE dicts, tau)
newMethod :: InstOrigin
-> TcId
pprInst m@(Method u id tys theta tau loc)
= hsep [ppr id, ptext SLIT("at"),
- brackets (interppSP tys) {- ,
+ brackets (sep (map pprParendType tys)) {- ,
ptext SLIT("theta"), ppr theta,
ptext SLIT("tau"), ppr tau
show_uniq u,
-- Dictionaries
lookupInst dict@(Dict _ (ClassP clas tys) loc)
- = tcGetInstEnv `thenNF_Tc` \ inst_env ->
- case lookupInstEnv inst_env clas tys of
+ = getDOptsTc `thenNF_Tc` \ dflags ->
+ tcGetInstEnv `thenNF_Tc` \ inst_env ->
+ case lookupInstEnv dflags inst_env clas tys of
FoundInst tenv dfun_id
-> let
Nothing -> tcInstTyVar tv `thenNF_Tc` \ tc_tv ->
returnTc (mkTyVarTy tc_tv)
in
+ -- It's possible that not all the tyvars are in
+ -- the substitution, tenv. For example:
+ -- instance C X a => D X where ...
+ -- (presumably there's a functional dependency in class C)
+ -- Hence the mk_ty_arg to instantiate any un-substituted tyvars.
mapNF_Tc mk_ty_arg tyvars `thenNF_Tc` \ ty_args ->
let
- subst = mkTyVarSubst tyvars ty_args
- dfun_rho = substTy subst rho
- (theta, _) = tcSplitRhoTy dfun_rho
- ty_app = mkHsTyApp (HsVar dfun_id) ty_args
+ dfun_rho = substTy (mkTyVarSubst tyvars ty_args) rho
+ (theta, _) = tcSplitRhoTy dfun_rho
+ ty_app = mkHsTyApp (HsVar dfun_id) ty_args
in
if null theta then
returnNF_Tc (SimpleInst ty_app)
-> NF_TcM (Maybe ThetaType) -- Here are the needed (c,t)s
lookupSimpleInst clas tys
- = tcGetInstEnv `thenNF_Tc` \ inst_env ->
- case lookupInstEnv inst_env clas tys of
+ = getDOptsTc `thenNF_Tc` \ dflags ->
+ tcGetInstEnv `thenNF_Tc` \ inst_env ->
+ case lookupInstEnv dflags inst_env clas tys of
FoundInst tenv dfun
-> returnNF_Tc (Just (substTheta (mkSubst emptyInScopeSet tenv) theta))
where