import FamInstEnv
import TcDeriv
import TcEnv
-import RnEnv ( lookupGlobalOccRn )
import RnSource ( addTcgDUs )
import TcHsType
import TcUnify
import DataCon
import Class
import Var
+import CoreUnfold ( mkDFunUnfolding )
+import CoreSyn ( Expr(Var) )
import Id
import MkId
import Name
-- A top-level definition for each instance method
-- Here op1_i, op2_i are the "instance method Ids"
+ -- The INLINE pragma comes from the user pragma
{-# INLINE [2] op1_i #-} -- From the instance decl bindings
op1_i, op2_i :: forall a. C a => forall b. Ix b => [a] -> b -> b
op1_i = /\a. \(d:C a).
op2_i = /\a \d:C a. $dmop2 [a] (df_i a d)
-- The dictionary function itself
- {-# INLINE df_i #-} -- Always inline dictionary functions
+ {-# NOINLINE CONLIKE df_i #-} -- Never inline dictionary functions
df_i :: forall a. C a -> C [a]
- df_i = /\a. \d:C a. letrec d' = MkC (op1_i a d)
- ($dmop2 [a] d')
- in d'
+ df_i = /\a. \d:C a. MkC (op1_i a d) (op2_i a d)
-- But see Note [Default methods in instances]
-- We can't apply the type checker to the default-method call
-* The dictionary function itself is inlined as vigorously as we
- possibly can, so that we expose that dictionary constructor to
- selectors as much as poss. That is why the op_i stuff is in
- *separate* bindings, so that the df_i binding is small enough
- to inline. See Note [Inline dfuns unconditionally].
+ -- Use a RULE to short-circuit applications of the class ops
+ {-# RULE "op1@C[a]" forall a, d:C a.
+ op1 [a] (df_i d) = op1_i a d #-}
+Note [Instances and loop breakers]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Note that df_i may be mutually recursive with both op1_i and op2_i.
It's crucial that df_i is not chosen as the loop breaker, even
though op1_i has a (user-specified) INLINE pragma.
- Not even once! Else op1_i, op2_i may be inlined into df_i.
* Instead the idea is to inline df_i into op1_i, which may then select
methods from the MkC record, and thereby break the recursion with
* If op1_i is marked INLINE by the user there's a danger that we won't
inline df_i in it, and that in turn means that (since it'll be a
loop-breaker because df_i isn't), op1_i will ironically never be
- inlined. We need to fix this somehow -- perhaps allowing inlining
- of INLINE functions inside other INLINE functions.
+ inlined. But this is OK: the recursion breaking happens by way of
+ a RULE (the magic ClassOp rule above), and RULES work inside InlineRule
+ unfoldings. See Note [RULEs enabled in SimplGently] in SimplUtils
+
+Note [ClassOp/DFun selection]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+One thing we see a lot is stuff like
+ op2 (df d1 d2)
+where 'op2' is a ClassOp and 'df' is DFun. Now, we could inline *both*
+'op2' and 'df' to get
+ case (MkD ($cop1 d1 d2) ($cop2 d1 d2) ... of
+ MkD _ op2 _ _ _ -> op2
+And that will reduce to ($cop2 d1 d2) which is what we wanted.
+
+But it's tricky to make this work in practice, because it requires us to
+inline both 'op2' and 'df'. But neither is keen to inline without having
+seen the other's result; and it's very easy to get code bloat (from the
+big intermediate) if you inline a bit too much.
+
+Instead we use a cunning trick.
+ * We arrange that 'df' and 'op2' NEVER inline.
+
+ * We arrange that 'df' is ALWAYS defined in the sylised form
+ df d1 d2 = MkD ($cop1 d1 d2) ($cop2 d1 d2) ...
+
+ * We give 'df' a magical unfolding (DFunUnfolding [$cop1, $cop2, ..])
+ that lists its methods.
+
+ * We make CoreUnfold.exprIsConApp_maybe spot a DFunUnfolding and return
+ a suitable constructor application -- inlining df "on the fly" as it
+ were.
+
+ * We give the ClassOp 'op2' a BuiltinRule that extracts the right piece
+ iff its argument satisfies exprIsConApp_maybe. This is done in
+ MkId mkDictSelId
+
+ * We make 'df' CONLIKE, so that shared uses stil match; eg
+ let d = df d1 d2
+ in ...(op2 d)...(op1 d)...
+
+Note [Single-method classes]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If the class has just one method (or, more accurately, just one element
+of {superclasses + methods}), then we still use the *same* strategy
+
+ class C a where op :: a -> a
+ instance C a => C [a] where op = <blah>
+
+We translate the class decl into a newtype, which just gives
+a top-level axiom:
+
+ axiom Co:C a :: C a ~ (a->a)
+
+ op :: forall a. C a -> (a -> a)
+ op a d = d |> (Co:C a)
+
+ MkC :: forall a. (a->a) -> C a
+ MkC = /\a.\op. op |> (sym Co:C a)
+
+ df :: forall a. C a => C [a]
+ {-# NOINLINE df DFun[ $cop_list ] #-}
+ df = /\a. \d. MkC ($cop_list a d)
+
+ $cop_list :: forall a. C a => [a] -> [a]
+ $cop_list = <blah>
+
+The "constructor" MkC expands to a cast, as does the class-op selector.
+The RULE works just like for multi-field dictionaries:
+
+ * (df a d) returns (Just (MkC,..,[$cop_list a d]))
+ to exprIsConApp_Maybe
+
+ * The RULE for op picks the right result
+
+This is a bit of a hack, because (df a d) isn't *really* a constructor
+application. But it works just fine in this case, exprIsConApp_maybe
+is otherwise used only when we hit a case expression which will have
+a real data constructor in it.
+
+The biggest reason for doing it this way, apart from uniformity, is
+that we want to be very careful when we have
+ instance C a => C [a] where
+ {-# INLINE op #-}
+ op = ...
+then we'll get an INLINE pragma on $cop_list but it's important that
+$cop_list only inlines when it's applied to *two* arguments (the
+dictionary and the list argument
+
+The danger is that we'll get something like
+ op_list :: C a => [a] -> [a]
+ op_list = /\a.\d. $cop_list a d
+and then we'll eta expand, and then we'll inline TOO EARLY. This happened in
+Trac #3772 and I spent far too long fiddling around trying to fix it.
+Look at the test for Trac #3772.
+
+ (Note: re-reading the above, I can't see how using the
+ uniform story solves the problem.)
Note [Subtle interaction of recursion and overlap]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
definition for 'this' in the definition of op1_i in the example above.
We can typecheck the defintion of local_op1, and when doing tcSimplifyCheck
we supply 'this' as a given dictionary. Only needed, though, if there
-are some type variales involved; otherwise there can be no overlap and
+are some type variables involved; otherwise there can be no overlap and
none of this arises.
Note [Tricky type variable scoping]
<dm-rhs> and for <rhs>, but that doesn't matter: the *renamer* will have
complained if 'b' is mentioned in <rhs>.
-Note [Inline dfuns unconditionally]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The code above unconditionally inlines dict funs. Here's why.
-Consider this program:
-
- test :: Int -> Int -> Bool
- test x y = (x,y) == (y,x) || test y x
- -- Recursive to avoid making it inline.
-
-This needs the (Eq (Int,Int)) instance. If we inline that dfun
-the code we end up with is good:
-
- Test.$wtest =
- \r -> case ==# [ww ww1] of wild {
- PrelBase.False -> Test.$wtest ww1 ww;
- PrelBase.True ->
- case ==# [ww1 ww] of wild1 {
- PrelBase.False -> Test.$wtest ww1 ww;
- PrelBase.True -> PrelBase.True [];
- };
- };
- Test.test = \r [w w1]
- case w of w2 {
- PrelBase.I# ww ->
- case w1 of w3 { PrelBase.I# ww1 -> Test.$wtest ww ww1; };
- };
-
-If we don't inline the dfun, the code is not nearly as good:
-
- (==) = case PrelTup.$fEq(,) PrelBase.$fEqInt PrelBase.$fEqInt of tpl {
- PrelBase.:DEq tpl1 tpl2 -> tpl2;
- };
-
- Test.$wtest =
- \r [ww ww1]
- let { y = PrelBase.I#! [ww1]; } in
- let { x = PrelBase.I#! [ww]; } in
- let { sat_slx = PrelTup.(,)! [y x]; } in
- let { sat_sly = PrelTup.(,)! [x y];
- } in
- case == sat_sly sat_slx of wild {
- PrelBase.False -> Test.$wtest ww1 ww;
- PrelBase.True -> PrelBase.True [];
- };
-
- Test.test =
- \r [w w1]
- case w of w2 {
- PrelBase.I# ww ->
- case w1 of w3 { PrelBase.I# ww1 -> Test.$wtest ww ww1; };
- };
-
-Why didn't GHC inline $fEq in those days? Because it looked big:
-
- PrelTup.zdfEqZ1T{-rcX-}
- = \ @ a{-reT-} :: * @ b{-reS-} :: *
- zddEq{-rf6-} _Ks :: {PrelBase.Eq{-23-} a{-reT-}}
- zddEq1{-rf7-} _Ks :: {PrelBase.Eq{-23-} b{-reS-}} ->
- let {
- zeze{-rf0-} _Kl :: (b{-reS-} -> b{-reS-} -> PrelBase.Bool{-3c-})
- zeze{-rf0-} = PrelBase.zeze{-01L-}@ b{-reS-} zddEq1{-rf7-} } in
- let {
- zeze1{-rf3-} _Kl :: (a{-reT-} -> a{-reT-} -> PrelBase.Bool{-3c-})
- zeze1{-rf3-} = PrelBase.zeze{-01L-} @ a{-reT-} zddEq{-rf6-} } in
- let {
- zeze2{-reN-} :: ((a{-reT-}, b{-reS-}) -> (a{-reT-}, b{-reS-})-> PrelBase.Bool{-3c-})
- zeze2{-reN-} = \ ds{-rf5-} _Ks :: (a{-reT-}, b{-reS-})
- ds1{-rf4-} _Ks :: (a{-reT-}, b{-reS-}) ->
- case ds{-rf5-}
- of wild{-reW-} _Kd { (a1{-rf2-} _Ks, a2{-reZ-} _Ks) ->
- case ds1{-rf4-}
- of wild1{-reX-} _Kd { (b1{-rf1-} _Ks, b2{-reY-} _Ks) ->
- PrelBase.zaza{-r4e-}
- (zeze1{-rf3-} a1{-rf2-} b1{-rf1-})
- (zeze{-rf0-} a2{-reZ-} b2{-reY-})
- }
- } } in
- let {
- a1{-reR-} :: ((a{-reT-}, b{-reS-})-> (a{-reT-}, b{-reS-})-> PrelBase.Bool{-3c-})
- a1{-reR-} = \ a2{-reV-} _Ks :: (a{-reT-}, b{-reS-})
- b1{-reU-} _Ks :: (a{-reT-}, b{-reS-}) ->
- PrelBase.not{-r6I-} (zeze2{-reN-} a2{-reV-} b1{-reU-})
- } in
- PrelBase.zdwZCDEq{-r8J-} @ (a{-reT-}, b{-reS-}) a1{-reR-} zeze2{-reN-})
-
-and it's not as bad as it seems, because it's further dramatically
-simplified: only zeze2 is extracted and its body is simplified.
%************************************************************************
-- round)
-- (1) Do class and family instance declarations
- ; let { idxty_decls = filter (isFamInstDecl . unLoc) tycl_decls }
+ ; idx_tycons <- mapAndRecoverM (tcFamInstDecl TopLevel) $
+ filter (isFamInstDecl . unLoc) tycl_decls
; local_info_tycons <- mapAndRecoverM tcLocalInstDecl1 inst_decls
- ; idx_tycons <- mapAndRecoverM tcIdxTyInstDeclTL idxty_decls
; let { (local_info,
at_tycons_s) = unzip local_info_tycons
; at_idx_tycons = concat at_tycons_s ++ idx_tycons
; clas_decls = filter (isClassDecl.unLoc) tycl_decls
; implicit_things = concatMap implicitTyThings at_idx_tycons
- ; aux_binds = mkAuxBinds at_idx_tycons
+ ; aux_binds = mkRecSelBinds at_idx_tycons
}
-- (2) Add the tycons of indexed types and their implicit
-- Next, construct the instance environment so far, consisting
-- of
- -- a) local instance decls
- -- b) generic instances
- -- c) local family instance decls
+ -- (a) local instance decls
+ -- (b) generic instances
+ -- (c) local family instance decls
; addInsts local_info $
addInsts generic_inst_info $
addFamInsts at_idx_tycons $ do {
generic_inst_info ++ deriv_inst_info ++ local_info,
aux_binds `plusHsValBinds` deriv_binds)
}}}
- where
- -- Make sure that toplevel type instance are not for associated types.
- -- !!!TODO: Need to perform this check for the TyThing of type functions,
- -- too.
- tcIdxTyInstDeclTL ldecl@(L loc decl) =
- do { tything <- tcFamInstDecl ldecl
- ; setSrcSpan loc $
- when (isAssocFamily tything) $
- addErr $ assocInClassErr (tcdName decl)
- ; return tything
- }
- isAssocFamily (ATyCon tycon) =
- case tyConFamInst_maybe tycon of
- Nothing -> panic "isAssocFamily: no family?!?"
- Just (fam, _) -> isTyConAssoc fam
- isAssocFamily _ = panic "isAssocFamily: no tycon?!?"
-
-assocInClassErr :: Name -> SDoc
-assocInClassErr name =
- ptext (sLit "Associated type") <+> quotes (ppr name) <+>
- ptext (sLit "must be inside a class instance")
addInsts :: [InstInfo Name] -> TcM a -> TcM a
addInsts infos thing_inside
; (tyvars, theta, tau) <- tcHsInstHead poly_ty
-- Now, check the validity of the instance.
- ; (clas, inst_tys) <- checkValidInstHead tau
- ; checkValidInstance tyvars theta clas inst_tys
+ ; (clas, inst_tys) <- checkValidInstance poly_ty tyvars theta tau
-- Next, process any associated types.
; idx_tycons <- recoverM (return []) $
- do { idx_tycons <- checkNoErrs $ mapAndRecoverM tcFamInstDecl ats
+ do { idx_tycons <- checkNoErrs $
+ mapAndRecoverM (tcFamInstDecl NotTopLevel) ats
; checkValidAndMissingATs clas (tyvars, inst_tys)
(zip ats idx_tycons)
; return idx_tycons }
\begin{code}
tcInstDecls2 :: [LTyClDecl Name] -> [InstInfo Name]
- -> TcM (LHsBinds Id, TcLclEnv)
+ -> TcM (LHsBinds Id)
-- (a) From each class declaration,
-- generate any default-method bindings
-- (b) From each instance decl
tcInstDecls2 tycl_decls inst_decls
= do { -- (a) Default methods from class decls
- (dm_binds_s, dm_ids_s) <- mapAndUnzipM tcClassDecl2 $
- filter (isClassDecl.unLoc) tycl_decls
- ; tcExtendIdEnv (concat dm_ids_s) $ do
-
+ let class_decls = filter (isClassDecl . unLoc) tycl_decls
+ ; dm_binds_s <- mapM tcClassDecl2 class_decls
+ ; let dm_binds = unionManyBags dm_binds_s
+
-- (b) instance declarations
- ; inst_binds_s <- mapM tcInstDecl2 inst_decls
+ ; let dm_ids = collectHsBindsBinders dm_binds
+ -- Add the default method Ids (again)
+ -- See Note [Default methods and instances]
+ ; inst_binds_s <- tcExtendIdEnv dm_ids $
+ mapM tcInstDecl2 inst_decls
-- Done
- ; let binds = unionManyBags dm_binds_s `unionBags`
- unionManyBags inst_binds_s
- ; tcl_env <- getLclEnv -- Default method Ids in here
- ; return (binds, tcl_env) }
+ ; return (dm_binds `unionBags` unionManyBags inst_binds_s) }
tcInstDecl2 :: InstInfo Name -> TcM (LHsBinds Id)
tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
addErrCtxt (instDeclCtxt2 (idType dfun_id)) $
tc_inst_decl2 dfun_id ibinds
where
- dfun_id = instanceDFunId ispec
- loc = getSrcSpan dfun_id
+ dfun_id = instanceDFunId ispec
+ loc = getSrcSpan dfun_id
\end{code}
+See Note [Default methods and instances]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The default method Ids are already in the type environment (see Note
+[Default method Ids and Template Haskell] in TcTyClsDcls), BUT they
+don't have their InlinePragmas yet. Usually that would not matter,
+because the simplifier propagates information from binding site to
+use. But, unusually, when compiling instance decls we *copy* the
+INLINE pragma from the default method to the method for that
+particular operation (see Note [INLINE and default methods] below).
+
+So right here in tcInstDecl2 we must re-extend the type envt with
+the default method Ids replete with their INLINE pragmas. Urk.
\begin{code}
tc_inst_decl2 :: Id -> InstBindings Name -> TcM (LHsBinds Id)
-- If there are no superclasses, matters are simpler, because we don't need the case
-- see Note [Newtype deriving superclasses] in TcDeriv.lhs
-tc_inst_decl2 dfun_id (NewTypeDerived coi)
- = do { let rigid_info = InstSkol
- origin = SigOrigin rigid_info
- inst_ty = idType dfun_id
+tc_inst_decl2 dfun_id (NewTypeDerived coi _)
+ = do { let rigid_info = InstSkol
+ origin = SigOrigin rigid_info
+ inst_ty = idType dfun_id
+ inst_tvs = fst (tcSplitForAllTys inst_ty)
; (inst_tvs', theta, inst_head_ty) <- tcSkolSigType rigid_info inst_ty
-- inst_head_ty is a PredType
(rep_ty, wrapper)
= case coi of
IdCo -> (last_ty, idHsWrapper)
- ACo co -> (snd (coercionKind co), WpCast (mk_full_coercion co))
+ ACo co -> (snd (coercionKind co'), WpCast (mk_full_coercion co'))
+ where
+ co' = substTyWith inst_tvs (mkTyVarTys inst_tvs') co
+ -- NB: the free variable of coi are bound by the
+ -- universally quantified variables of the dfun_id
+ -- This is weird, and maybe we should make NewTypeDerived
+ -- carry a type-variable list too; but it works fine
-----------------------
-- mk_full_coercion
; let coerced_rep_dict = wrapId wrapper (instToId rep_dict)
; body <- make_body cls_tycon cls_inst_tys sc_dicts coerced_rep_dict
- ; let dict_bind = noLoc $ VarBind (instToId this_dict) (noLoc body)
+ ; let dict_bind = mkVarBind (instToId this_dict) (noLoc body)
; return (unitBag $ noLoc $
AbsBinds inst_tvs' (map instToVar dfun_dicts)
- [(inst_tvs', dfun_id, instToId this_dict, [])]
+ [(inst_tvs', dfun_id, instToId this_dict, noSpecPrags)]
(dict_bind `consBag` sc_binds)) }
where
-----------------------
-- Ordinary instances
tc_inst_decl2 dfun_id (VanillaInst monobinds uprags standalone_deriv)
- = do { let rigid_info = InstSkol
- inst_ty = idType dfun_id
+ = do { let rigid_info = InstSkol
+ inst_ty = idType dfun_id
+ loc = getSrcSpan dfun_id
-- Instantiate the instance decl with skolem constants
; (inst_tyvars', dfun_theta', inst_head') <- tcSkolSigType rigid_info inst_ty
-- bizarre, but OK so long as you realise it!
; let
(clas, inst_tys') = tcSplitDFunHead inst_head'
- (class_tyvars, sc_theta, _, op_items) = classBigSig clas
+ (class_tyvars, sc_theta, sc_sels, op_items) = classBigSig clas
-- Instantiate the super-class context with inst_tys
sc_theta' = substTheta (zipOpenTvSubst class_tyvars inst_tys') sc_theta
origin = SigOrigin rigid_info
-- Create dictionary Ids from the specified instance contexts.
- ; sc_loc <- getInstLoc InstScOrigin
- ; sc_dicts <- newDictOccs sc_loc sc_theta' -- These are wanted
; inst_loc <- getInstLoc origin
; dfun_dicts <- newDictBndrs inst_loc dfun_theta' -- Includes equalities
; this_dict <- newDictBndr inst_loc (mkClassPred clas inst_tys')
-
-- Default-method Ids may be mentioned in synthesised RHSs,
-- but they'll already be in the environment.
- -- Typecheck the methods
- ; let this_dict_id = instToId this_dict
+
+ -- Cook up a binding for "this = df d1 .. dn",
+ -- to use in each method binding
+ -- Need to clone the dict in case it is floated out, and
+ -- then clashes with its friends
+ ; cloned_this <- cloneDict this_dict
+ ; let cloned_this_bind = mkVarBind (instToId cloned_this) $
+ L loc $ wrapId app_wrapper dfun_id
+ app_wrapper = mkWpApps dfun_lam_vars <.> mkWpTyApps (mkTyVarTys inst_tyvars')
dfun_lam_vars = map instToVar dfun_dicts -- Includes equalities
- prag_fn = mkPragFun uprags
- loc = getSrcSpan dfun_id
- tc_meth = tcInstanceMethod loc standalone_deriv
- clas inst_tyvars' dfun_dicts
- dfun_theta' inst_tys'
- this_dict dfun_id
- prag_fn monobinds
- ; (meth_exprs, meth_binds) <- tcExtendTyVarEnv inst_tyvars' $
- mapAndUnzipM tc_meth op_items
+ nested_this_pair
+ | null inst_tyvars' && null dfun_theta' = (this_dict, emptyBag)
+ | otherwise = (cloned_this, unitBag cloned_this_bind)
+
+ -- Deal with 'SPECIALISE instance' pragmas
+ -- See Note [SPECIALISE instance pragmas]
+ ; let spec_inst_sigs = filter isSpecInstLSig uprags
+ -- The filter removes the pragmas for methods
+ ; spec_inst_prags <- mapM (wrapLocM (tcSpecInst dfun_id)) spec_inst_sigs
+
+ -- Typecheck the methods
+ ; let prag_fn = mkPragFun uprags monobinds
+ tc_meth = tcInstanceMethod loc standalone_deriv
+ clas inst_tyvars'
+ dfun_dicts inst_tys'
+ nested_this_pair
+ prag_fn spec_inst_prags monobinds
+
+ ; (meth_ids, meth_binds) <- tcExtendTyVarEnv inst_tyvars' $
+ mapAndUnzipM tc_meth op_items
-- Figure out bindings for the superclass context
- -- Don't include this_dict in the 'givens', else
- -- sc_dicts get bound by just selecting from this_dict!!
- ; sc_binds <- addErrCtxt superClassCtxt $
- tcSimplifySuperClasses inst_loc this_dict dfun_dicts sc_dicts
- -- Note [Recursive superclasses]
+ ; sc_loc <- getInstLoc InstScOrigin
+ ; sc_dicts <- newDictOccs sc_loc sc_theta' -- These are wanted
+ ; let tc_sc = tcSuperClass inst_loc inst_tyvars' dfun_dicts nested_this_pair
+ ; (sc_ids, sc_binds) <- mapAndUnzipM tc_sc (sc_sels `zip` sc_dicts)
- -- It's possible that the superclass stuff might unified something
- -- in the envt with one of the inst_tyvars'
+ -- It's possible that the superclass stuff might unified
+ -- something in the envt with one of the inst_tyvars'
; checkSigTyVars inst_tyvars'
- -- Deal with 'SPECIALISE instance' pragmas
- ; prags <- tcPrags dfun_id (filter isSpecInstLSig uprags)
-
-- Create the result bindings
; let dict_constr = classDataCon clas
- inline_prag | null dfun_dicts = []
- | otherwise = [L loc (InlinePrag (alwaysInlineSpec FunLike))]
- -- Always inline the dfun; this is an experimental decision
- -- because it makes a big performance difference sometimes.
- -- Often it means we can do the method selection, and then
- -- inline the method as well. Marcin's idea; see comments below.
- --
- -- BUT: don't inline it if it's a constant dictionary;
- -- we'll get all the benefit without inlining, and we get
- -- a **lot** of code duplication if we inline it
- --
- -- See Note [Inline dfuns] below
-
- sc_dict_vars = map instToVar sc_dicts
- dict_bind = L loc (VarBind this_dict_id dict_rhs)
- dict_rhs = foldl (\ f a -> L loc (HsApp f (L loc a))) inst_constr meth_exprs
- inst_constr = L loc $ wrapId (mkWpApps sc_dict_vars <.> mkWpTyApps inst_tys')
- (dataConWrapId dict_constr)
+ this_dict_id = instToId this_dict
+ dict_bind = mkVarBind this_dict_id dict_rhs
+ dict_rhs = foldl mk_app inst_constr sc_meth_ids
+ sc_meth_ids = sc_ids ++ meth_ids
+ inst_constr = L loc $ wrapId (mkWpTyApps inst_tys')
+ (dataConWrapId dict_constr)
-- 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
-- member) are dealt with by the common MkId.mkDataConWrapId code rather
-- than needing to be repeated here.
+ mk_app :: LHsExpr Id -> Id -> LHsExpr Id
+ mk_app fun arg_id = L loc (HsApp fun (L loc (wrapId arg_wrapper arg_id)))
+ arg_wrapper = mkWpApps dfun_lam_vars <.> mkWpTyApps (mkTyVarTys inst_tyvars')
+
+ -- Do not inline the dfun; instead give it a magic DFunFunfolding
+ -- See Note [ClassOp/DFun selection]
+ -- See also note [Single-method classes]
+ dfun_id_w_fun = dfun_id
+ `setIdUnfolding` mkDFunUnfolding inst_ty (map Var sc_meth_ids)
+ `setInlinePragma` dfunInlinePragma
+
+ main_bind = AbsBinds
+ inst_tyvars'
+ dfun_lam_vars
+ [(inst_tyvars', dfun_id_w_fun, this_dict_id, SpecPrags spec_inst_prags)]
+ (unitBag dict_bind)
- main_bind = noLoc $ AbsBinds
- inst_tyvars'
- dfun_lam_vars
- [(inst_tyvars', dfun_id, this_dict_id, inline_prag ++ prags)]
- (dict_bind `consBag` sc_binds)
+ ; showLIE (text "instance")
+ ; return (unitBag (L loc main_bind) `unionBags`
+ listToBag meth_binds `unionBags`
+ listToBag sc_binds)
+ }
+
+{-
+ -- Create the result bindings
+ ; let this_dict_id = instToId this_dict
+ arg_ids = sc_ids ++ meth_ids
+ arg_binds = listToBag meth_binds `unionBags`
+ listToBag sc_binds
; showLIE (text "instance")
- ; return (main_bind `consBag` unionManyBags meth_binds) }
+ ; case newTyConCo_maybe (classTyCon clas) of
+ Nothing -- A multi-method class
+ -> return (unitBag (L loc data_bind) `unionBags` arg_binds)
+ where
+ data_dfun_id = dfun_id -- Do not inline; instead give it a magic DFunFunfolding
+ -- See Note [ClassOp/DFun selection]
+ `setIdUnfolding` mkDFunUnfolding dict_constr arg_ids
+ `setInlinePragma` dfunInlinePragma
+
+ data_bind = AbsBinds inst_tyvars' dfun_lam_vars
+ [(inst_tyvars', data_dfun_id, this_dict_id, spec_inst_prags)]
+ (unitBag dict_bind)
+
+ dict_bind = mkVarBind this_dict_id dict_rhs
+ dict_rhs = foldl mk_app inst_constr arg_ids
+ dict_constr = classDataCon clas
+ inst_constr = L loc $ wrapId (mkWpTyApps inst_tys')
+ (dataConWrapId dict_constr)
+ -- 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.
+
+ mk_app :: LHsExpr Id -> Id -> LHsExpr Id
+ mk_app fun arg_id = L loc (HsApp fun (L loc (wrapId arg_wrapper arg_id)))
+ arg_wrapper = mkWpApps dfun_lam_vars <.> mkWpTyApps (mkTyVarTys inst_tyvars')
+
+ Just the_nt_co -- (Just co) for a single-method class
+ -> return (unitBag (L loc nt_bind) `unionBags` arg_binds)
+ where
+ nt_dfun_id = dfun_id -- Just let the dfun inline; see Note [Single-method classes]
+ `setInlinePragma` alwaysInlinePragma
+
+ local_nt_dfun = setIdType this_dict_id inst_ty -- A bit of a hack, but convenient
+
+ nt_bind = AbsBinds [] []
+ [([], nt_dfun_id, local_nt_dfun, spec_inst_prags)]
+ (unitBag (mkVarBind local_nt_dfun (L loc (wrapId nt_cast the_meth_id))))
+
+ the_meth_id = ASSERT( length arg_ids == 1 ) head arg_ids
+ nt_cast = WpCast $ mkPiTypes (inst_tyvars' ++ dfun_lam_vars) $
+ mkSymCoercion (mkTyConApp the_nt_co inst_tys')
+-}
+
+------------------------------
+tcSuperClass :: InstLoc -> [TyVar] -> [Inst]
+ -> (Inst, LHsBinds Id)
+ -> (Id, Inst) -> TcM (Id, LHsBind Id)
+-- Build a top level decl like
+-- sc_op = /\a \d. let this = ... in
+-- let sc = ... in
+-- sc
+-- The "this" part is just-in-case (discarded if not used)
+-- See Note [Recursive superclasses]
+tcSuperClass inst_loc tyvars dicts (this_dict, this_bind)
+ (sc_sel, sc_dict)
+ = addErrCtxt superClassCtxt $
+ do { sc_binds <- tcSimplifySuperClasses inst_loc
+ this_dict dicts [sc_dict]
+ -- Don't include this_dict in the 'givens', else
+ -- sc_dicts get bound by just selecting from this_dict!!
+
+ ; uniq <- newUnique
+ ; let sc_op_ty = mkSigmaTy tyvars (map dictPred dicts)
+ (mkPredTy (dictPred sc_dict))
+ sc_op_name = mkDerivedInternalName mkClassOpAuxOcc uniq
+ (getName sc_sel)
+ sc_op_id = mkLocalId sc_op_name sc_op_ty
+ sc_id = instToVar sc_dict
+ sc_op_bind = AbsBinds tyvars
+ (map instToVar dicts)
+ [(tyvars, sc_op_id, sc_id, noSpecPrags)]
+ (this_bind `unionBags` sc_binds)
+
+ ; return (sc_op_id, noLoc sc_op_bind) }
\end{code}
Note [Recursive superclasses]
loop. What we need is to add this_dict to Avails without adding its
superclasses, and we currently have no way to do that.
+Note [SPECIALISE instance pragmas]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+
+ instance (Ix a, Ix b) => Ix (a,b) where
+ {-# SPECIALISE instance Ix (Int,Int) #-}
+ range (x,y) = ...
+
+We do *not* want to make a specialised version of the dictionary
+function. Rather, we want specialised versions of each method.
+Thus we should generate something like this:
+
+ $dfIx :: (Ix a, Ix x) => Ix (a,b)
+ {- DFUN [$crange, ...] -}
+ $dfIx da db = Ix ($crange da db) (...other methods...)
+
+ $dfIxPair :: (Ix a, Ix x) => Ix (a,b)
+ {- DFUN [$crangePair, ...] -}
+ $dfIxPair = Ix ($crangePair da db) (...other methods...)
+
+ $crange :: (Ix a, Ix b) -> ((a,b),(a,b)) -> [(a,b)]
+ {-# SPECIALISE $crange :: ((Int,Int),(Int,Int)) -> [(Int,Int)] #-}
+ $crange da db = <blah>
+
+ {-# RULE range ($dfIx da db) = $crange da db #-}
+
+Note that
+
+ * The RULE is unaffected by the specialisation. We don't want to
+ specialise $dfIx, because then it would need a specialised RULE
+ which is a pain. The single RULE works fine at all specialisations.
+ See Note [How instance declarations are translated] above
+
+ * Instead, we want to specialise the *method*, $crange
+
+In practice, rather than faking up a SPECIALISE pragama for each
+method (which is painful, since we'd have to figure out its
+specialised type), we call tcSpecPrag *as if* were going to specialise
+$dfIx -- you can see that in the call to tcSpecInst. That generates a
+SpecPrag which, as it turns out, can be used unchanged for each method.
+The "it turns out" bit is delicate, but it works fine!
+
+\begin{code}
+tcSpecInst :: Id -> Sig Name -> TcM TcSpecPrag
+tcSpecInst dfun_id prag@(SpecInstSig hs_ty)
+ = addErrCtxt (spec_ctxt prag) $
+ do { let name = idName dfun_id
+ ; (tyvars, theta, tau) <- tcHsInstHead hs_ty
+ ; let spec_ty = mkSigmaTy tyvars theta tau
+ ; co_fn <- tcSubExp (SpecPragOrigin name) (idType dfun_id) spec_ty
+ ; return (SpecPrag co_fn defaultInlinePragma) }
+ where
+ spec_ctxt prag = hang (ptext (sLit "In the SPECIALISE pragma")) 2 (ppr prag)
+
+tcSpecInst _ _ = panic "tcSpecInst"
+\end{code}
%************************************************************************
%* *
\begin{code}
tcInstanceMethod :: SrcSpan -> Bool -> Class -> [TcTyVar] -> [Inst]
- -> TcThetaType -> [TcType]
- -> Inst -> Id
- -> TcPragFun -> LHsBinds Name
+ -> [TcType]
+ -> (Inst, LHsBinds Id) -- "This" and its binding
+ -> TcPragFun -- Local prags
+ -> [Located TcSpecPrag] -- Arising from 'SPECLALISE instance'
+ -> LHsBinds Name
-> (Id, DefMeth)
- -> TcM (HsExpr Id, LHsBinds Id)
+ -> TcM (Id, LHsBind Id)
-- The returned inst_meth_ids all have types starting
-- forall tvs. theta => ...
-tcInstanceMethod loc standalone_deriv clas tyvars dfun_dicts theta inst_tys
- this_dict dfun_id prag_fn binds_in (sel_id, dm_info)
- = do { cloned_this <- cloneDict this_dict
- -- Need to clone the dict in case it is floated out, and
- -- then clashes with its friends
- ; uniq1 <- newUnique
- ; let local_meth_name = mkInternalName uniq1 sel_occ loc -- Same OccName
- this_dict_bind = L loc $ VarBind (instToId cloned_this) $
- L loc $ wrapId meth_wrapper dfun_id
- mb_this_bind | null tyvars = Nothing
- | otherwise = Just (cloned_this, this_dict_bind)
- -- Only need the this_dict stuff if there are type variables
- -- involved; otherwise overlap is not possible
- -- See Note [Subtle interaction of recursion and overlap]
-
+tcInstanceMethod loc standalone_deriv clas tyvars dfun_dicts inst_tys
+ (this_dict, this_dict_bind)
+ prag_fn spec_inst_prags binds_in (sel_id, dm_info)
+ = do { uniq <- newUnique
+ ; let meth_name = mkDerivedInternalName mkClassOpAuxOcc uniq sel_name
+ ; local_meth_name <- newLocalName sel_name
+ -- Base the local_meth_name on the selector name, becuase
+ -- type errors from tcInstanceMethodBody come from here
+
+ ; let local_meth_ty = instantiateMethod clas sel_id inst_tys
+ meth_ty = mkSigmaTy tyvars (map dictPred dfun_dicts) local_meth_ty
+ meth_id = mkLocalId meth_name meth_ty
+ local_meth_id = mkLocalId local_meth_name local_meth_ty
+
+ --------------
tc_body rn_bind
= add_meth_ctxt rn_bind $
- do { (meth_id, tc_binds) <- tcInstanceMethodBody
- InstSkol clas tyvars dfun_dicts theta inst_tys
- mb_this_bind sel_id
- local_meth_name
- meth_sig_fn meth_prag_fn rn_bind
- ; return (wrapId meth_wrapper meth_id, tc_binds) }
-
- ; case (findMethodBind sel_name local_meth_name binds_in, dm_info) of
- -- There is a user-supplied method binding, so use it
- (Just user_bind, _) -> tc_body user_bind
-
+ do { (meth_id1, spec_prags) <- tcPrags NonRecursive False True
+ meth_id (prag_fn sel_name)
+ ; bind <- tcInstanceMethodBody (instLoc this_dict)
+ tyvars dfun_dicts
+ ([this_dict], this_dict_bind)
+ meth_id1 local_meth_id
+ meth_sig_fn
+ (SpecPrags (spec_inst_prags ++ spec_prags))
+ rn_bind
+ ; return (meth_id1, bind) }
+
+ --------------
+ tc_default :: DefMeth -> TcM (Id, LHsBind Id)
-- The user didn't supply a method binding, so we have to make
-- up a default binding, in a way depending on the default-method info
- (Nothing, GenDefMeth) -> do -- Derivable type classes stuff
- { meth_bind <- mkGenericDefMethBind clas inst_tys sel_id local_meth_name
- ; tc_body meth_bind }
-
- (Nothing, NoDefMeth) -> do -- No default method in the class
- { warn <- doptM Opt_WarnMissingMethods
- ; warnTc (warn -- Warn only if -fwarn-missing-methods
- && not (startsWithUnderscore (getOccName sel_id)))
- -- Don't warn about _foo methods
- omitted_meth_warn
- ; return (error_rhs, emptyBag) }
-
- (Nothing, DefMeth) -> do -- An polymorphic default method
- { -- Build the typechecked version directly,
- -- without calling typecheck_method;
- -- see Note [Default methods in instances]
- dm_name <- lookupGlobalOccRn (mkDefMethRdrName sel_name)
- -- Might not be imported, but will be an OrigName
- ; dm_id <- tcLookupId dm_name
- ; return (wrapId dm_wrapper dm_id, emptyBag) } }
+ tc_default NoDefMeth -- No default method at all
+ = do { warnMissingMethod sel_id
+ ; return (meth_id, mkVarBind meth_id $
+ mkLHsWrap lam_wrapper error_rhs) }
+
+ tc_default GenDefMeth -- Derivable type classes stuff
+ = do { meth_bind <- mkGenericDefMethBind clas inst_tys sel_id local_meth_name
+ ; tc_body meth_bind }
+
+ tc_default (DefMeth dm_name) -- An polymorphic default method
+ = do { -- Build the typechecked version directly,
+ -- without calling typecheck_method;
+ -- see Note [Default methods in instances]
+ -- Generate /\as.\ds. let this = df as ds
+ -- in $dm inst_tys this
+ -- The 'let' is necessary only because HsSyn doesn't allow
+ -- you to apply a function to a dictionary *expression*.
+
+ ; dm_id <- tcLookupId dm_name
+ ; let dm_inline_prag = idInlinePragma dm_id
+ rhs = HsWrap (WpApp (instToId this_dict) <.> mkWpTyApps inst_tys) $
+ HsVar dm_id
+
+ meth_bind = L loc $ VarBind { var_id = local_meth_id
+ , var_rhs = L loc rhs
+ , var_inline = False }
+ meth_id1 = meth_id `setInlinePragma` dm_inline_prag
+ -- Copy the inline pragma (if any) from the default
+ -- method to this version. Note [INLINE and default methods]
+
+ bind = AbsBinds { abs_tvs = tyvars, abs_dicts = dfun_lam_vars
+ , abs_exports = [( tyvars, meth_id1, local_meth_id
+ , SpecPrags spec_inst_prags)]
+ , abs_binds = this_dict_bind `unionBags` unitBag meth_bind }
+ -- Default methods in an instance declaration can't have their own
+ -- INLINE or SPECIALISE pragmas. It'd be possible to allow them, but
+ -- currently they are rejected with
+ -- "INLINE pragma lacks an accompanying binding"
+
+ ; return (meth_id1, L loc bind) }
+
+ ; case findMethodBind sel_name local_meth_name binds_in of
+ Just user_bind -> tc_body user_bind -- User-supplied method binding
+ Nothing -> tc_default dm_info -- None supplied
+ }
where
sel_name = idName sel_id
- sel_occ = nameOccName sel_name
- this_dict_id = instToId this_dict
-
- meth_prag_fn _ = prag_fn sel_name
- meth_sig_fn _ = Just [] -- The 'Just' says "yes, there's a type sig"
- -- But there are no scoped type variables from local_method_id
- -- Only the ones from the instance decl itself, which are already
- -- in scope. Example:
- -- class C a where { op :: forall b. Eq b => ... }
- -- instance C [c] where { op = <rhs> }
- -- In <rhs>, 'c' is scope but 'b' is not!
-
- error_rhs = HsApp error_fun error_msg
+
+ meth_sig_fn _ = Just [] -- The 'Just' says "yes, there's a type sig"
+ -- But there are no scoped type variables from local_method_id
+ -- Only the ones from the instance decl itself, which are already
+ -- in scope. Example:
+ -- class C a where { op :: forall b. Eq b => ... }
+ -- instance C [c] where { op = <rhs> }
+ -- In <rhs>, 'c' is scope but 'b' is not!
+
+ error_rhs = L loc $ HsApp error_fun error_msg
error_fun = L loc $ wrapId (WpTyApp meth_tau) nO_METHOD_BINDING_ERROR_ID
error_msg = L loc (HsLit (HsStringPrim (mkFastString error_string)))
meth_tau = funResultTy (applyTys (idType sel_id) inst_tys)
error_string = showSDoc (hcat [ppr loc, text "|", ppr sel_id ])
- dm_wrapper = WpApp this_dict_id <.> mkWpTyApps inst_tys
-
- omitted_meth_warn :: SDoc
- omitted_meth_warn = ptext (sLit "No explicit method nor default method for")
- <+> quotes (ppr sel_id)
-
dfun_lam_vars = map instToVar dfun_dicts
- meth_wrapper = mkWpApps dfun_lam_vars <.> mkWpTyApps (mkTyVarTys tyvars)
+ lam_wrapper = mkWpTyLams tyvars <.> mkWpLams dfun_lam_vars
-- For instance decls that come from standalone deriving clauses
-- we want to print out the full source code if there's an error
= vcat [ ptext (sLit "When typechecking a standalone-derived method for")
<+> quotes (pprClassPred clas tys) <> colon
, nest 2 $ pprSetDepth AllTheWay $ ppr bind ]
+
+warnMissingMethod :: Id -> TcM ()
+warnMissingMethod sel_id
+ = do { warn <- doptM Opt_WarnMissingMethods
+ ; warnTc (warn -- Warn only if -fwarn-missing-methods
+ && not (startsWithUnderscore (getOccName sel_id)))
+ -- Don't warn about _foo methods
+ (ptext (sLit "No explicit method nor default method for")
+ <+> quotes (ppr sel_id)) }
\end{code}
+Note [Export helper functions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We arrange to export the "helper functions" of an instance declaration,
+so that they are not subject to preInlineUnconditionally, even if their
+RHS is trivial. Reason: they are mentioned in the DFunUnfolding of
+the dict fun as Ids, not as CoreExprs, so we can't substitute a
+non-variable for them.
+
+We could change this by making DFunUnfoldings have CoreExprs, but it
+seems a bit simpler this way.
+
Note [Default methods in instances]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this
class Baz v x where
foo :: x -> x
- foo y = y
+ foo y = <blah>
instance Baz Int Int
From the class decl we get
$dmfoo :: forall v x. Baz v x => x -> x
+ $dmfoo y = <blah>
+
+Notice that the type is ambiguous. That's fine, though. The instance
+decl generates
+
+ $dBazIntInt = MkBaz fooIntInt
+ fooIntInt = $dmfoo Int Int $dBazIntInt
+
+BUT this does mean we must generate the dictionary translation of
+fooIntInt directly, rather than generating source-code and
+type-checking it. That was the bug in Trac #1061. In any case it's
+less work to generate the translated version!
+
+Note [INLINE and default methods]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Default methods need special case. They are supposed to behave rather like
+macros. For exmample
+
+ class Foo a where
+ op1, op2 :: Bool -> a -> a
+
+ {-# INLINE op1 #-}
+ op1 b x = op2 (not b) x
+
+ instance Foo Int where
+ -- op1 via default method
+ op2 b x = <blah>
+
+The instance declaration should behave
+
+ just as if 'op1' had been defined with the
+ code, and INLINE pragma, from its original
+ definition.
+
+That is, just as if you'd written
+
+ instance Foo Int where
+ op2 b x = <blah>
+
+ {-# INLINE op1 #-}
+ op1 b x = op2 (not b) x
+
+So for the above example we generate:
+
+
+ {-# INLINE $dmop1 #-}
+ -- $dmop1 has an InlineCompulsory unfolding
+ $dmop1 d b x = op2 d (not b) x
+
+ $fFooInt = MkD $cop1 $cop2
+
+ {-# INLINE $cop1 #-}
+ $cop1 = $dmop1 $fFooInt
+
+ $cop2 = <blah>
+
+Note carefullly:
+
+* We *copy* any INLINE pragma from the default method $dmop1 to the
+ instance $cop1. Otherwise we'll just inline the former in the
+ latter and stop, which isn't what the user expected
-Notice that the type is ambiguous. That's fine, though. The instance decl generates
+* Regardless of its pragma, we give the default method an
+ unfolding with an InlineCompulsory source. That means
+ that it'll be inlined at every use site, notably in
+ each instance declaration, such as $cop1. This inlining
+ must happen even though
+ a) $dmop1 is not saturated in $cop1
+ b) $cop1 itself has an INLINE pragma
- $dBazIntInt = MkBaz ($dmfoo Int Int $dBazIntInt)
+ It's vital that $dmop1 *is* inlined in this way, to allow the mutual
+ recursion between $fooInt and $cop1 to be broken
-BUT this does mean we must generate the dictionary translation directly, rather
-than generating source-code and type-checking it. That was the bug ing
-Trac #1061. In any case it's less work to generate the translated version!
+* To communicate the need for an InlineCompulsory to the desugarer
+ (which makes the Unfoldings), we use the IsDefaultMethod constructor
+ in TcSpecPrags.
%************************************************************************
instDeclCtxt2 dfun_ty
= inst_decl_ctxt (ppr (mkClassPred cls tys))
where
- (_,_,cls,tys) = tcSplitDFunTy dfun_ty
+ (_,cls,tys) = tcSplitDFunTy dfun_ty
inst_decl_ctxt :: SDoc -> SDoc
inst_decl_ctxt doc = ptext (sLit "In the instance declaration for") <+> quotes doc