tidyInsts, tidyMoreInsts,
- newDictsFromOld, newDicts, cloneDict,
+ newDictsFromOld, newDicts, newDictsAtLoc, cloneDict,
newOverloadedLit, newIPDict,
newMethod, newMethodFromName, newMethodWithGivenTy,
- tcInstClassOp, tcInstCall, tcInstDataCon,
+ tcInstClassOp, tcInstCall, tcInstStupidTheta,
tcSyntaxName, tcStdSyntaxName,
tyVarsOfInst, tyVarsOfInsts, tyVarsOfLIE,
import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType,
zonkTcThetaType, tcInstTyVar, tcInstType, tcInstTyVars
)
-import TcType ( Type, TcType, TcThetaType, TcTyVarSet,
- PredType(..), TyVarDetails(VanillaTv), typeKind,
- tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
+import TcType ( Type, TcType, TcThetaType, TcTyVarSet, TcTyVar,
+ PredType(..), typeKind,
+ tcSplitForAllTys, tcSplitForAllTys,
tcSplitPhiTy, tcIsTyVarTy, tcSplitDFunTy,
isIntTy,isFloatTy, isIntegerTy, isDoubleTy,
tcIsTyVarTy, mkPredTy, mkTyVarTy, mkTyVarTys,
tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tidyPred,
isClassPred, isTyVarClassPred, isLinearPred,
getClassPredTys, getClassPredTys_maybe, mkPredName,
- isInheritablePred, isIPPred, matchTys,
+ isInheritablePred, isIPPred,
tidyType, tidyTypes, tidyFreeTyVars, tcSplitSigmaTy,
pprPred, pprParendType, pprThetaArrow, pprTheta, pprClassPred
)
+import Type ( substTy, substTys, substTyWith, substTheta, zipTopTvSubst )
+import Unify ( matchTys )
import Kind ( isSubKind )
import HscTypes ( ExternalPackageState(..) )
import CoreFVs ( idFreeTyVars )
-import DataCon ( DataCon,dataConSig )
-import Id ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId, setIdUnique )
+import DataCon ( DataCon, dataConTyVars, dataConStupidTheta, dataConName )
+import Id ( Id, idName, idType, mkUserLocal, mkLocalId )
import PrelInfo ( isStandardClass, isNoDictClass )
-import Name ( Name, mkMethodOcc, getOccName, getSrcLoc, isHomePackageName, isInternalName )
+import Name ( Name, mkMethodOcc, getOccName, getSrcLoc, isHomePackageName,
+ isInternalName, setNameUnique, mkSystemNameEncoded )
import NameSet ( addOneToNameSet )
-import Subst ( substTy, substTyWith, substTheta, mkTopTyVarSubst )
import Literal ( inIntRange )
import Var ( TyVar, tyVarKind )
-import VarEnv ( TidyEnv, emptyTidyEnv, lookupSubstEnv, SubstResult(..) )
+import VarEnv ( TidyEnv, emptyTidyEnv, lookupVarEnv )
import VarSet ( elemVarSet, emptyVarSet, unionVarSet, mkVarSet )
import TysWiredIn ( floatDataCon, doubleDataCon )
import PrelNames ( integerTyConName, fromIntegerName, fromRationalName, rationalTyConName )
import BasicTypes( IPName(..), mapIPName, ipNameName )
import UniqSupply( uniqsFromSupply )
import SrcLoc ( mkSrcSpan, noLoc, unLoc, Located(..) )
-import CmdLineOpts( DynFlags, DynFlag( Opt_AllowUndecidableInstances ), dopt )
+import CmdLineOpts( DynFlags )
import Maybes ( isJust )
import Outputable
\end{code}
instName inst = idName (instToId inst)
instToId :: Inst -> TcId
-instToId (Dict id _ _) = id
+instToId (LitInst nm _ ty _) = mkLocalId nm ty
+instToId (Dict nm pred _) = mkLocalId nm (mkPredTy pred)
instToId (Method id _ _ _ _ _) = id
-instToId (LitInst id _ _ _) = id
instLoc (Dict _ _ loc) = loc
instLoc (Method _ _ _ _ _ loc) = loc
newDictsAtLoc loc theta
cloneDict :: Inst -> TcM Inst
-cloneDict (Dict id ty loc) = newUnique `thenM` \ uniq ->
- returnM (Dict (setIdUnique id uniq) ty loc)
+cloneDict (Dict nm ty loc) = newUnique `thenM` \ uniq ->
+ returnM (Dict (setNameUnique nm uniq) ty loc)
newDictsFromOld :: Inst -> TcThetaType -> TcM [Inst]
newDictsFromOld (Dict _ _ loc) theta = newDictsAtLoc loc theta
= newUniqueSupply `thenM` \ us ->
returnM (zipWith mk_dict (uniqsFromSupply us) theta)
where
- mk_dict uniq pred = Dict (mkLocalId (mkPredName uniq loc pred) (mkPredTy pred))
+ mk_dict uniq pred = Dict (mkPredName uniq loc pred)
pred inst_loc
loc = instLocSrcLoc inst_loc
let
pred = IParam ip_name ty
name = mkPredName uniq (instLocSrcLoc inst_loc) pred
- id = mkLocalId name (mkPredTy pred)
+ dict = Dict name pred inst_loc
in
- returnM (mapIPName (\n -> id) ip_name, Dict id pred inst_loc)
+ returnM (mapIPName (\n -> instToId dict) ip_name, dict)
\end{code}
\begin{code}
-tcInstCall :: InstOrigin -> TcType -> TcM (ExprCoFn, TcType)
+tcInstCall :: InstOrigin -> TcType -> TcM (ExprCoFn, [TcTyVar], TcType)
tcInstCall orig fun_ty -- fun_ty is usually a sigma-type
- = tcInstType VanillaTv fun_ty `thenM` \ (tyvars, theta, tau) ->
- newDicts orig theta `thenM` \ dicts ->
- extendLIEs dicts `thenM_`
- let
- inst_fn e = DictApp (mkHsTyApp (noLoc e) (mkTyVarTys tyvars)) (map instToId dicts)
- in
- returnM (mkCoercion inst_fn, tau)
-
-tcInstDataCon :: InstOrigin
- -> TyVarDetails -- Use this for the existential tyvars
- -- ExistTv when pattern-matching,
- -- VanillaTv at a call of the constructor
- -> DataCon
- -> TcM ([TcType], -- Types to instantiate at
- [Inst], -- Existential dictionaries to apply to
- [TcType], -- Argument types of constructor
- TcType, -- Result type
- [TyVar]) -- Existential tyvars
-tcInstDataCon orig ex_tv_details data_con
- = let
- (tvs, stupid_theta, ex_tvs, ex_theta, arg_tys, tycon) = dataConSig data_con
- -- We generate constraints for the stupid theta even when
- -- pattern matching (as the Report requires)
- in
- mappM (tcInstTyVar VanillaTv) tvs `thenM` \ tvs' ->
- mappM (tcInstTyVar ex_tv_details) ex_tvs `thenM` \ ex_tvs' ->
- let
- tv_tys' = mkTyVarTys tvs'
- ex_tv_tys' = mkTyVarTys ex_tvs'
- all_tys' = tv_tys' ++ ex_tv_tys'
-
- tenv = mkTopTyVarSubst (tvs ++ ex_tvs) all_tys'
- stupid_theta' = substTheta tenv stupid_theta
- ex_theta' = substTheta tenv ex_theta
- arg_tys' = map (substTy tenv) arg_tys
- result_ty' = mkTyConApp tycon tv_tys'
- in
- newDicts orig stupid_theta' `thenM` \ stupid_dicts ->
- newDicts orig ex_theta' `thenM` \ ex_dicts ->
-
- -- Note that we return the stupid theta *only* in the LIE;
- -- we don't otherwise use it at all
- extendLIEs stupid_dicts `thenM_`
-
- returnM (all_tys', ex_dicts, arg_tys', result_ty', ex_tvs')
+ = do { (tyvars, theta, tau) <- tcInstType fun_ty
+ ; dicts <- newDicts orig theta
+ ; extendLIEs dicts
+ ; let inst_fn e = unLoc (mkHsDictApp (mkHsTyApp (noLoc e) (mkTyVarTys tyvars))
+ (map instToId dicts))
+ ; return (mkCoercion inst_fn, tyvars, tau) }
+
+tcInstStupidTheta :: DataCon -> [TcType] -> TcM ()
+-- Instantiate the "stupid theta" of the data con, and throw
+-- the constraints into the constraint set
+tcInstStupidTheta data_con inst_tys
+ | null stupid_theta
+ = return ()
+ | otherwise
+ = do { stupid_dicts <- newDicts (OccurrenceOf (dataConName data_con))
+ (substTheta tenv stupid_theta)
+ ; extendLIEs stupid_dicts }
+ where
+ stupid_theta = dataConStupidTheta data_con
+ tenv = zipTopTvSubst (dataConTyVars data_con) inst_tys
newMethodFromName :: InstOrigin -> TcType -> Name -> TcM TcId
newMethodFromName origin ty name
then return ()
else do
{ traceTc (text "checkKind: adding kind constraint" <+> ppr tv <+> ppr ty)
- ; tv1 <- tcInstTyVar VanillaTv tv
+ ; tv1 <- tcInstTyVar tv
; unifyTauTy (mkTyVarTy tv1) ty1 }}
= getInstLoc orig `thenM` \ loc ->
newUnique `thenM` \ new_uniq ->
let
- lit_inst = LitInst lit_id lit expected_ty loc
- lit_id = mkSysLocal FSLIT("lit") new_uniq expected_ty
+ lit_nm = mkSystemNameEncoded new_uniq FSLIT("lit")
+ -- The "encoded" bit means that we don't need to z-encode
+ -- the string every time we call this!
+ lit_inst = LitInst lit_nm lit expected_ty loc
in
extendLIE lit_inst `thenM_`
returnM (L (instLocSrcSpan loc) (HsVar (instToId lit_inst)))
%* *
%************************************************************************
-Zonking makes sure that the instance types are fully zonked,
-but doesn't do the same for any of the Ids in an Inst. There's no
-need, and it's a lot of extra work.
+Zonking makes sure that the instance types are fully zonked.
\begin{code}
zonkInst :: Inst -> TcM Inst
-zonkInst (Dict id pred loc)
+zonkInst (Dict name pred loc)
= zonkTcPredType pred `thenM` \ new_pred ->
- returnM (Dict id new_pred loc)
+ returnM (Dict name new_pred loc)
zonkInst (Method m id tys theta tau loc)
= zonkId id `thenM` \ new_id ->
zonkTcType tau `thenM` \ new_tau ->
returnM (Method m new_id new_tys new_theta new_tau loc)
-zonkInst (LitInst id lit ty loc)
+zonkInst (LitInst nm lit ty loc)
= zonkTcType ty `thenM` \ new_ty ->
- returnM (LitInst id lit new_ty loc)
+ returnM (LitInst nm lit new_ty loc)
zonkInsts insts = mappM zonkInst insts
\end{code}
pprInst, pprInstInFull :: Inst -> SDoc
-- Debugging: print the evidence :: type
-pprInst (LitInst id lit ty loc) = ppr id <+> dcolon <+> ppr ty
-pprInst (Dict id pred loc) = ppr id <+> dcolon <+> pprPred pred
+pprInst (LitInst nm lit ty loc) = ppr nm <+> dcolon <+> ppr ty
+pprInst (Dict nm pred loc) = ppr nm <+> dcolon <+> pprPred pred
pprInst m@(Method inst_id id tys theta tau loc)
= ppr inst_id <+> dcolon <+>
, let (_, theta, clas, tys) = tcSplitDFunTy (idType dfun) ]
-- Print without the for-all, which the programmer doesn't write
-show_uniq u = ifPprDebug (text "{-" <> ppr u <> text "-}")
-
tidyInst :: TidyEnv -> Inst -> Inst
-tidyInst env (LitInst u lit ty loc) = LitInst u lit (tidyType env ty) loc
-tidyInst env (Dict u pred loc) = Dict u (tidyPred env pred) loc
+tidyInst env (LitInst nm lit ty loc) = LitInst nm lit (tidyType env ty) loc
+tidyInst env (Dict nm pred loc) = Dict nm (tidyPred env pred) loc
tidyInst env (Method u id tys theta tau loc) = Method u id (tidyTypes env tys) theta tau loc
tidyMoreInsts :: TidyEnv -> [Inst] -> (TidyEnv, [Inst])
addInst dflags home_ie dfun
= do { -- Load imported instances, so that we report
-- duplicates correctly
- pkg_ie <- loadImportedInsts cls tys
+ let (tvs, _, cls, tys) = tcSplitDFunTy (idType dfun)
+ ; pkg_ie <- loadImportedInsts cls tys
-- Check functional dependencies
; case checkFunDeps (pkg_ie, home_ie) dfun of
Nothing -> return ()
-- Check for duplicate instance decls
- ; let { (matches, _) = lookupInstEnv dflags (pkg_ie, home_ie) cls tys
+ -- We instantiate the dfun type because the instance lookup
+ -- requires nice fresh types in the thing to be looked up
+ ; (tvs', _, tenv) <- tcInstTyVars tvs
+ ; let { tys' = substTys tenv tys
+ ; (matches, _) = lookupInstEnv dflags (pkg_ie, home_ie) cls tys'
; dup_dfuns = [dup_dfun | (_, (_, dup_tys, dup_dfun)) <- matches,
- isJust (matchTys (mkVarSet tvs) tys dup_tys)] }
+ isJust (matchTys (mkVarSet tvs) tys' dup_tys)] }
-- Find memebers of the match list which
-- dfun itself matches. If the match is 2-way, it's a duplicate
; case dup_dfuns of
-- OK, now extend the envt
; return (extendInstEnv home_ie dfun) }
- where
- (tvs, _, cls, tys) = tcSplitDFunTy (idType dfun)
+
traceDFuns dfuns
= traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
2 (pprDFuns [dfun, dup_dfun]))
addDictLoc dfun thing_inside
- = addSrcSpan (mkSrcSpan loc loc) thing_inside
+ = setSrcSpan (mkSrcSpan loc loc) thing_inside
where
loc = getSrcLoc dfun
\end{code}
-- may have done some unification by now]
-lookupInst inst@(LitInst u (HsIntegral i from_integer_name) ty loc)
+lookupInst inst@(LitInst _nm (HsIntegral i from_integer_name) ty loc)
| Just expr <- shortCutIntLit i ty
= returnM (GenInst [] expr) -- GenInst, not SimpleInst, because
-- expr may be a constructor application
(mkHsApp (L (instLocSrcSpan loc)
(HsVar (instToId method_inst))) integer_lit))
-lookupInst inst@(LitInst u (HsFractional f from_rat_name) ty loc)
+lookupInst inst@(LitInst _nm (HsFractional f from_rat_name) ty loc)
| Just expr <- shortCutFracLit f ty
= returnM (GenInst [] expr)
-----------------
instantiate_dfun tenv dfun_id pred loc
- = traceTc (text "lookupInst success" <+>
+ = -- tenv is a substitution that instantiates the dfun_id
+ -- to match the requested result type. However, the dfun
+ -- might have some tyvars that only appear in arguments
+ -- dfun :: forall a b. C a b, Ord b => D [a]
+ -- We instantiate b to a flexi type variable -- it'll presumably
+ -- become fixed later via functional dependencies
+ traceTc (text "lookupInst success" <+>
vcat [text "dict" <+> ppr pred,
text "witness" <+> ppr dfun_id <+> ppr (idType dfun_id) ]) `thenM_`
-- Record that this dfun is needed
(topIdLvl dfun_id) use_stage `thenM_`
let
(tyvars, rho) = tcSplitForAllTys (idType dfun_id)
- mk_ty_arg tv = case lookupSubstEnv tenv tv of
- Just (DoneTy ty) -> returnM ty
- Nothing -> tcInstTyVar VanillaTv tv `thenM` \ tc_tv ->
- returnM (mkTyVarTy tc_tv)
+ mk_ty_arg tv = case lookupVarEnv tenv tv of
+ Just ty -> returnM ty
+ Nothing -> tcInstTyVar tv `thenM` \ tc_tv ->
+ returnM (mkTyVarTy tc_tv)
in
mappM mk_ty_arg tyvars `thenM` \ ty_args ->
let
- dfun_rho = substTy (mkTopTyVarSubst tyvars ty_args) rho
+ dfun_rho = substTy (zipTopTvSubst tyvars ty_args) rho
-- Since the tyvars are freshly made,
-- they cannot possibly be captured by
- -- any existing for-alls. Hence mkTopTyVarSubst
+ -- any existing for-alls. Hence zipTopTyVarSubst
(theta, _) = tcSplitPhiTy dfun_rho
ty_app = mkHsTyApp (L (instLocSrcSpan loc) (HsVar dfun_id)) ty_args
in
dfun_name = idName dfun_id
tcGetInstEnvs :: TcM (InstEnv, InstEnv)
--- Gets both the home-pkg inst env (includes module being compiled)
--- and the external-package inst-env
+-- Gets both the external-package inst-env
+-- and the home-pkg inst env (includes module being compiled)
tcGetInstEnvs = do { eps <- getEps; env <- getGblEnv;
- return (tcg_inst_env env, eps_inst_env eps) }
+ return (eps_inst_env eps, tcg_inst_env env) }
\end{code}