+\begin{code}
+tcInstId :: Id -> NF_TcM (TcExpr, LIE, TcType)
+tcInstId fun
+ = loop (HsVar fun) emptyLIE (idType fun)
+ where
+ orig = OccurrenceOf fun
+ loop fun lie fun_ty = tcInstType fun_ty `thenNF_Tc` \ (tyvars, theta, tau) ->
+ loop_help fun lie (mkTyVarTys tyvars) theta tau
+
+ loop_help fun lie arg_tys [] tau -- Not overloaded
+ = returnNF_Tc (mkHsTyApp fun arg_tys, lie, tau)
+
+ loop_help (HsVar fun_id) lie arg_tys theta tau
+ | can_share theta -- Sharable method binding
+ = newMethodWithGivenTy orig fun_id arg_tys theta tau `thenNF_Tc` \ meth ->
+ loop (HsVar (instToId meth))
+ (unitLIE meth `plusLIE` lie) tau
+
+ loop_help fun lie arg_tys theta tau -- The general case
+ = newDicts orig theta `thenNF_Tc` \ dicts ->
+ loop (mkHsDictApp (mkHsTyApp fun arg_tys) (map instToId dicts))
+ (mkLIE dicts `plusLIE` lie) tau
+
+ can_share theta | opt_NoMethodSharing = False
+ | otherwise = not (any isLinearPred theta)
+ -- This is a slight hack.
+ -- If f :: (%x :: T) => Int -> Int
+ -- Then if we have two separate calls, (f 3, f 4), we cannot
+ -- make a method constraint that then gets shared, thus:
+ -- let m = f %x in (m 3, m 4)
+ -- because that loses the linearity of the constraint.
+ -- The simplest thing to do is never to construct a method constraint
+ -- in the first place that has a linear implicit parameter in it.
+