tyVarsOfType, tyVarsOfTypes, tyVarsOfTheta, applyTys,
mkForAllTys, boxedTypeKind
)
-import PprType ( {- instance Outputable Type -} )
-import Subst ( Subst, mkSubst, substTy, emptySubst, substBndrs, extendSubstList,
- substId, substAndCloneId, substAndCloneIds, lookupIdSubst
+import Subst ( Subst, mkSubst, substTy, mkSubst, substBndrs, extendSubstList,
+ substId, substAndCloneId, substAndCloneIds, lookupIdSubst, substInScope
)
import Var ( TyVar, mkSysTyVar, setVarUnique )
import VarSet
import CoreFVs ( exprFreeVars, exprsFreeVars )
import CoreLint ( beginPass, endPass )
import PprCore ( pprCoreRules )
-import Rules ( addIdSpecialisations )
+import Rules ( addIdSpecialisations, lookupRule )
import UniqSupply ( UniqSupply,
UniqSM, initUs_, thenUs, thenUs_, returnUs, getUniqueUs,
)
import Name ( nameOccName, mkSpecOcc, getSrcLoc )
import FiniteMap
-import Maybes ( MaybeErr(..), catMaybes )
+import Maybes ( MaybeErr(..), catMaybes, maybeToBool )
import ErrUtils ( dumpIfSet )
import Bag
import List ( partition )
return binds'
where
+ -- We need to start with a Subst that knows all the things
+ -- that are in scope, so that the substitution engine doesn't
+ -- accidentally re-use a unique that's already in use
+ -- Easiest thing is to do it all at once, as if all the top-level
+ -- decls were mutually recursive
+ top_subst = mkSubst (mkVarSet (bindersOfBinds binds)) emptySubstEnv
+
go [] = returnSM ([], emptyUDs)
go (bind:binds) = go binds `thenSM` \ (binds', uds) ->
- specBind emptySubst bind uds `thenSM` \ (bind', uds') ->
+ specBind top_subst bind uds `thenSM` \ (bind', uds') ->
returnSM (bind' ++ binds', uds')
dump_specs var = pprCoreRules var (idSpecialisation var)
returnSM (App fun' arg', uds_arg `plusUDs` uds_app)
go (Var f) args = case specVar subst f of
- Var f' -> returnSM (Var f', mkCallUDs f' args)
+ Var f' -> returnSM (Var f', mkCallUDs subst f' args)
e' -> returnSM (e', emptyUDs) -- I don't expect this!
go other args = specExpr subst other
returnSM (Case scrut' case_bndr' alts', uds_scrut `plusUDs` uds_alts)
where
(subst_alt, case_bndr') = substId subst case_bndr
+ -- No need to clone case binder; it can't float like a let(rec)
spec_alt (con, args, rhs)
= specExpr subst_rhs rhs `thenSM` \ (rhs', uds) ->
-- It's role as a holder for a call instance is o'er
-- But it might be alive for some other reason by now.
- fn_type = idType fn
- (tyvars, theta, tau) = splitSigmaTy fn_type
- n_tyvars = length tyvars
- n_dicts = length theta
+ fn_type = idType fn
+ (tyvars, theta, _) = splitSigmaTy fn_type
+ n_tyvars = length tyvars
+ n_dicts = length theta
(rhs_tyvars, rhs_ids, rhs_body) = collectTyAndValBinders rhs
rhs_dicts = take n_dicts rhs_ids
unionCalls :: CallDetails -> CallDetails -> CallDetails
unionCalls c1 c2 = plusFM_C plusFM c1 c2
-singleCall :: (Id, [Maybe Type], [DictExpr]) -> CallDetails
-singleCall (id, tys, dicts)
+singleCall :: Id -> [Maybe Type] -> [DictExpr] -> CallDetails
+singleCall id tys dicts
= unitFM id (unitFM tys (dicts, call_fvs))
where
call_fvs = exprsFreeVars dicts `unionVarSet` tys_fvs
(tys,dicts) <- fmToList fm
]
-mkCallUDs f args
+mkCallUDs subst f args
| null theta
|| length spec_tys /= n_tyvars
|| length dicts /= n_dicts
- = emptyUDs -- Not overloaded
+ || maybeToBool (lookupRule (substInScope subst) f args)
+ -- There's already a rule covering this call. A typical case
+ -- is where there's an explicit user-provided rule. Then
+ -- we don't want to create a specialised version
+ -- of the function that overlaps.
+ = emptyUDs -- Not overloaded, or no specialisation wanted
| otherwise
= MkUD {dict_binds = emptyBag,
- calls = singleCall (f, spec_tys, dicts)
+ calls = singleCall f spec_tys dicts
}
where
- (tyvars, theta, tau) = splitSigmaTy (idType f)
- constrained_tyvars = tyVarsOfTheta theta
- n_tyvars = length tyvars
- n_dicts = length theta
+ (tyvars, theta, _) = splitSigmaTy (idType f)
+ constrained_tyvars = tyVarsOfTheta theta
+ n_tyvars = length tyvars
+ n_dicts = length theta
spec_tys = [mk_spec_ty tv ty | (tv, Type ty) <- tyvars `zip` args]
dicts = [dict_expr | (_, dict_expr) <- theta `zip` (drop n_tyvars args)]