2 % (c) The GRASP/AQUA Project, Glasgow University, 1998
4 \section[UsageSPInf]{UsageSP Inference Engine}
6 This code is (based on) PhD work of Keith Wansbrough <kw217@cl.cam.ac.uk>,
7 September 1998 .. May 1999.
9 Keith Wansbrough 1998-09-04..1999-05-05
12 module UsageSPInf ( doUsageSPInf ) where
14 #include "HsVersions.h"
21 import Type ( Type(..), TyNote(..), UsageAnn(..),
23 splitFunTy_maybe, splitFunTys, splitTyConApp_maybe,
24 mkUsgTy, splitUsgTy, isUsgTy, isNotUsgTy, unUsgTy, tyUsg,
26 import TyCon ( tyConArgVrcs_maybe )
27 import DataCon ( dataConType )
28 import Const ( Con(..), Literal(..), literalType )
29 import Var ( IdOrTyVar, UVar, varType, mkUVar, modifyIdInfo )
30 import IdInfo ( setLBVarInfo, LBVarInfo(..) )
32 import UniqSupply ( UniqSupply, UniqSM,
33 initUs, splitUniqSupply )
35 import CmdLineOpts ( opt_D_dump_usagesp, opt_DoUSPLinting )
36 import ErrUtils ( doIfSet, dumpIfSet )
37 import PprCore ( pprCoreBindings )
40 ======================================================================
45 For full details, see _Once Upon a Polymorphic Type_, University of
46 Glasgow Department of Computing Science Technical Report TR-1998-19,
47 December 1998, or the summary in POPL'99.
49 Inference is performed as follows:
51 1. Remove all manipulable[*] annotations and add fresh @UVar@
54 2. Walk over the resulting term applying the type rules and
55 collecting the constraints.
57 3. Find the solution to the constraints and apply the substitution
58 to the annotations, leaving a @UVar@-free term.
60 [*] A manipulable annotation is one derived from the current source
61 module, as opposed to one derived from an import, which we are clearly
64 As in the paper, a ``tau-type'' is a type that does *not* have an
65 annotation on top (although it may have some inside), and a
66 ``sigma-type'' is one that does (i.e., is a tau-type with an
67 annotation added). This conflicts with the totally unrelated usage of
68 these terms in the remainder of GHC. Caveat lector! KSW 1999-04.
71 The inference is done over a set of @CoreBind@s, and inside the IO
75 doUsageSPInf :: UniqSupply
79 doUsageSPInf us binds = do
80 let binds1 = doUnAnnotBinds binds
82 (us1,us2) = splitUniqSupply us
83 (binds2,_) = doAnnotBinds us1 binds1
85 dumpIfSet opt_D_dump_usagesp "UsageSPInf reannot'd" $
86 pprCoreBindings binds2
88 doIfSet opt_DoUSPLinting $
89 doLintUSPAnnotsBinds binds2 -- lint check 0
91 let ((ucs,_),_) = initUs us2 (uniqSMMToUs (usgInfBinds binds2))
95 Nothing -> panic "doUsageSPInf: insol. conset!"
96 binds3 = appUSubstBinds s binds2
98 doIfSet opt_DoUSPLinting $
99 do doLintUSPAnnotsBinds binds3 -- lint check 1
100 doLintUSPConstBinds binds3 -- lint check 2 (force solution)
101 doCheckIfWorseUSP binds binds3 -- check for worsening of usages
103 dumpIfSet opt_D_dump_usagesp "UsageSPInf" $
104 pprCoreBindings binds3
109 ======================================================================
111 Inferring an expression
112 ~~~~~~~~~~~~~~~~~~~~~~~
114 When we infer types for an expression, we expect it to be already
115 annotated - normally with usage variables everywhere (or possibly
116 constants). No context is required since variables already know their
120 usgInfBinds :: [CoreBind]
124 usgInfBinds [] = return (emptyUConSet,
127 usgInfBinds (b:bs) = do { (ucs2,fv2) <- usgInfBinds bs -- careful of scoping here
128 ; (ucs1,fv1) <- usgInfBind b fv2
129 ; return (ucs1 `unionUCS` ucs2,
133 usgInfBind :: CoreBind -- CoreBind to infer for
134 -> VarMultiset -- fvs of `body' (later CoreBinds)
135 -> UniqSMM (UConSet, -- constraints generated by this CoreBind
136 VarMultiset) -- fvs of this CoreBind and later ones
138 usgInfBind (NonRec v1 e1) fv0 = do { (ty1u,ucs1,fv1) <- usgInfCE e1
139 ; let ty2u = varType v1
140 ucs2 = usgSubTy ty1u ty2u
141 ucs3 = occChkUConSet v1 fv0
142 ; return (unionUCSs [ucs1,ucs2,ucs3],
143 fv1 `plusMS` (fv0 `delFromMS` v1))
146 usgInfBind (Rec ves) fv0 = do { tuf1s <- mapM (usgInfCE . snd) ves
147 ; let (ty1us,ucs1s,fv1s) = unzip3 tuf1s
149 ucs2s = zipWith usgSubTy ty1us (map varType vs)
150 fv3 = foldl plusMS fv0 fv1s
151 ucs3 = occChksUConSet vs fv3
152 ; return (unionUCSs (ucs1s ++ ucs2s ++ [ucs3]),
153 foldl delFromMS fv3 vs)
157 -> UniqSMM (Type,UConSet,VarMultiset)
158 -- ^- in the unique supply monad for new uvars
159 -- ^- type of the @CoreExpr@ (always a sigma type)
160 -- ^- set of constraints arising
161 -- ^- variable appearances for occur()
163 usgInfCE e0@(Var v) | isTyVar v = panic "usgInfCE: unexpected TyVar"
164 | otherwise = return (ASSERT( isUsgTy (varType v) )
169 usgInfCE e0@(Con (Literal lit) args) = ASSERT( null args )
170 do { u1 <- newVarUSMM (Left e0)
171 ; return (mkUsgTy u1 (literalType lit),
176 usgInfCE (Con DEFAULT _) = panic "usgInfCE: DEFAULT"
178 usgInfCE e0@(Con con args) = -- constant or primop. guaranteed saturated.
179 do { let (ety1s,e1s) = span isTypeArg args
180 ty1s = map (\ (Type ty) -> ty) ety1s -- univ. + exist.
181 ; (ty3us,ty3u) <- case con of
182 DataCon c -> do { u4 <- newVarUSMM (Left e0)
183 ; return $ dataConTys c u4 ty1s
184 -- ty1s is exdicts + args
186 PrimOp p -> return $ primOpUsgTys p ty1s
187 otherwise -> panic "usgInfCE: unrecognised Con"
188 ; tuf4s <- mapM usgInfCE e1s
189 ; let (ty4us,ucs4s,fv4s) = unzip3 tuf4s
190 ucs5s = zipWith usgSubTy
193 -- note ty3 is T ty1s, so it already
194 -- has annotations inside where they
195 -- should be (for datacons); for
196 -- primops we assume types are
197 -- appropriately annotated already.
198 unionUCSs (ucs4s ++ ucs5s),
199 foldl plusMS emptyMS fv4s)
201 where dataConTys c u tys = -- compute argtys of a datacon
202 let rawCTy = dataConType c
203 cTy = ASSERT( isUnAnnotated rawCTy )
204 -- algebraic data types are defined entirely
205 -- unannotated; we place Many annotations inside
206 -- them to get the required tau-types (p20(fn) TR)
208 -- we really don't want annots on top of the
209 -- funargs, but we can't easily avoid
210 -- this so we use unUsgTy later
211 (ty3us,ty3) = ASSERT( all isNotUsgTy tys )
212 splitFunTys (applyTys cTy tys)
213 -- safe 'cos a DataCon always returns a
214 -- value of type (TyCon tys), not an
216 ty3u = if null ty3us then mkUsgTy u ty3 else ty3
217 -- if no args, ty3 is tau; else already sigma
218 reUsg = mkUsgTy u . unUsgTy
222 usgInfCE (App e1 (Type ty2)) = do { (ty1u,ucs,fv) <- usgInfCE e1
223 ; let (u,ty1) = splitUsgTy ty1u
224 ; ASSERT( isNotUsgTy ty2 )
225 return (mkUsgTy u (applyTy ty1 ty2),
230 usgInfCE (App e1 e2) = do { (ty1u,ucs1,fv1) <- usgInfCE e1
231 ; (ty2u,ucs2,fv2) <- usgInfCE e2
232 ; let (u1,ty1) = splitUsgTy ty1u
233 (ty3u,ty4u) = case splitFunTy_maybe ty1 of
235 Nothing -> panic "usgInfCE: app of non-funty"
236 ucs5 = usgSubTy ty2u ty3u
237 ; return (ASSERT( isUsgTy ty4u )
239 unionUCSs [ucs1,ucs2,ucs5],
243 usgInfCE (Lam v e) | isTyVar v = do { (ty1u,ucs,fv) <- usgInfCE e -- safe to ignore free v here
244 ; let (u,ty1) = splitUsgTy ty1u
245 ; return (mkUsgTy u (mkForAllTy v ty1),
249 | otherwise = panic "usgInfCE: missing lambda usage annot"
250 -- if used for checking also, may need to extend this case to
251 -- look in lbvarInfo instead.
253 usgInfCE (Note (TermUsg u) (Lam v e))
254 = ASSERT( not (isTyVar v) )
255 do { (ty1u,ucs1,fv) <- usgInfCE e
256 ; let ty2u = varType v
257 ucs2 = occChkUConSet v fv
258 fv' = fv `delFromMS` v
259 ucs3s = foldMS (\v _ ucss -> (leqUConSet u ((tyUsg . varType) v)
260 : ucss)) -- in reverse order!
263 ; return (mkUsgTy u (mkFunTy ty2u ty1u),
264 unionUCSs ([ucs1,ucs2] ++ ucs3s),
268 usgInfCE (Let bind e0) = do { (ty0u,ucs0,fv0) <- usgInfCE e0
269 ; (ucs1,fv1) <- usgInfBind bind fv0
270 ; return (ASSERT( isUsgTy ty0u )
272 ucs0 `unionUCS` ucs1,
276 usgInfCE (Case e0 v0 [(DEFAULT,[],e1)])
277 = -- pure strict let, no selection (could be at polymorphic or function type)
278 do { (ty0u,ucs0,fv0) <- usgInfCE e0
279 ; (ty1u,ucs1,fv1) <- usgInfCE e1
280 ; let (u0,ty0) = splitUsgTy ty0u
281 ucs2 = usgEqTy ty0u (varType v0) -- messy! but OK
282 ; ty4u <- freshannotTy ty1u
283 ; let ucs5 = usgSubTy ty1u ty4u
284 ucs7 = occChkUConSet v0 (fv1 `plusMS` (unitMS v0))
285 ; return (ASSERT( isUsgTy ty4u )
287 unionUCSs [ucs0,ucs1,ucs2,ucs5,ucs7],
288 fv0 `plusMS` (fv1 `delFromMS` v0))
291 usgInfCE expr@(Case e0 v0 alts)
292 = -- general case (tycon of scrutinee must be known)
293 do { let (cs,vss,es) = unzip3 alts
294 ; (ty0u,ucs0,fv0) <- usgInfCE e0
295 ; tuf2s <- mapM usgInfCE es
296 ; let (u0,ty0) = splitUsgTy ty0u
297 ucs1 = usgEqTy ty0u (varType v0) -- messy! but OK
298 (tc,ty0ks) = case splitTyConApp_maybe ty0 of
300 Nothing -> pprPanic "usgInfCE: weird:" $
301 vcat [text "scrutinee:" <+> ppr e0,
302 text "type:" <+> ppr ty0u]
303 ; let (ty2us,ucs2s,fv2s) = unzip3 tuf2s
304 ucs3ss = ASSERT2( all isNotUsgTy ty0ks, text "expression" <+> ppr e0 $$ text "has type" <+> ppr ty0u )
305 zipWith (\ c vs -> zipWith (\ty v ->
306 usgSubTy (mkUsgTy u0 ty)
308 (caseAltArgs ty0ks c)
312 ; ty4u <- freshannotTy (head ty2us) -- assume at least one alt
313 ; let ucs5s = zipWith usgSubTy ty2us (repeat ty4u)
314 ucs6s = zipWith occChksUConSet vss fv2s
315 fv7 = ASSERT( not (null fv2s) && (length fv2s == length vss) )
316 foldl1 maxMS (zipWith (foldl delFromMS) fv2s vss)
317 ucs7 = occChkUConSet v0 (fv7 `plusMS` (unitMS v0))
318 ; return (ASSERT( isUsgTy ty4u )
320 unionUCSs ([ucs0,ucs1] ++ ucs2s
325 fv0 `plusMS` (fv7 `delFromMS` v0))
327 where caseAltArgs :: [Type] -> Con -> [Type]
328 -- compute list of tau-types required by a case-alt
329 caseAltArgs tys (DataCon dc) = let rawCTy = dataConType dc
330 cTy = ASSERT2( isUnAnnotated rawCTy, (text "caseAltArgs: rawCTy annotated!:" <+> ppr rawCTy <+> text "in" <+> ppr expr) )
332 in ASSERT( all isNotUsgTy tys )
333 map unUsgTy (fst (splitFunTys (applyTys cTy tys)))
334 caseAltArgs tys (Literal _) = []
335 caseAltArgs tys DEFAULT = []
336 caseAltArgs tys (PrimOp _) = panic "caseAltArgs: unexpected PrimOp"
338 usgInfCE (Note (SCC _) e) = usgInfCE e
340 usgInfCE (Note (Coerce ty1 ty0) e)
341 = do { (ty2u,ucs2,fv2) <- usgInfCE e
342 ; let (u2,ty2) = splitUsgTy ty2u
343 ucs3 = usgEqTy ty0 ty2 -- messy but OK
344 ty0' = (annotManyN . unannotTy) ty0 -- really nasty type
345 ucs4 = usgEqTy ty0 ty0'
347 -- What this says is that a Coerce does the most general possible
348 -- annotation to what's inside it (nasty, nasty), because no information
349 -- can pass through a Coerce. It of course simply ignores the info
350 -- that filters down through into ty1, because it can do nothing with it.
351 -- It does still pass through the topmost usage annotation, though.
352 ; return (mkUsgTy u2 ty1,
353 unionUCSs [ucs2,ucs3,ucs4,ucs5],
357 usgInfCE (Note InlineCall e) = usgInfCE e
359 usgInfCE (Note (TermUsg u) e) = pprTrace "usgInfCE: ignoring extra TermUsg:" (ppr u) $
362 usgInfCE (Type ty) = panic "usgInfCE: unexpected Type"
365 ======================================================================
370 If a variable appears more than once in an fv set, force its usage to be Many.
373 occChkUConSet :: IdOrTyVar
377 occChkUConSet v fv = if occInMS v fv > 1
378 then eqManyUConSet ((tyUsg . varType) v)
381 occChksUConSet :: [IdOrTyVar]
385 occChksUConSet vs fv = unionUCSs (map (\v -> occChkUConSet v fv) vs)
389 Subtyping and equal-typing relations. These generate constraint sets.
390 Both assume their arguments are annotated correctly, and are either
391 both tau-types or both sigma-types (in fact, are both exactly the same
395 usgSubTy ty1 ty2 = genUsgCmpTy cmp ty1 ty2
396 where cmp u1 u2 = leqUConSet u2 u1
398 usgEqTy ty1 ty2 = genUsgCmpTy cmp ty1 ty2 -- **NB** doesn't equate tyconargs that
399 -- don't appear (see below)
400 where cmp u1 u2 = eqUConSet u1 u2
402 genUsgCmpTy :: (UsageAnn -> UsageAnn -> UConSet) -- constraint (u1 REL u2), respectively
407 genUsgCmpTy cmp (NoteTy (UsgNote u1) ty1) (NoteTy (UsgNote u2) ty2)
408 = cmp u1 u2 `unionUCS` genUsgCmpTy cmp ty1 ty2
411 -- deal with omitted == UsMany
412 genUsgCmpTy cmp (NoteTy (UsgNote u1) ty1) ty2
413 = cmp u1 UsMany `unionUCS` genUsgCmpTy cmp ty1 ty2
414 genUsgCmpTy cmp ty1 (NoteTy (UsgNote u2) ty2)
415 = cmp UsMany u2 `unionUCS` genUsgCmpTy cmp ty1 ty2
418 genUsgCmpTy cmp (NoteTy (SynNote sty1) ty1) (NoteTy (SynNote sty2) ty2)
419 = genUsgCmpTy cmp sty1 sty2 `unionUCS` genUsgCmpTy cmp ty1 ty2
420 -- **! is this right? or should I throw away synonyms, or sth else?
422 -- if SynNote only on one side, throw it out
423 genUsgCmpTy cmp (NoteTy (SynNote sty1) ty1) ty2
424 = genUsgCmpTy cmp ty1 ty2
425 genUsgCmpTy cmp ty1 (NoteTy (SynNote sty2) ty2)
426 = genUsgCmpTy cmp ty1 ty2
429 genUsgCmpTy cmp (NoteTy (FTVNote _) ty1) ty2
430 = genUsgCmpTy cmp ty1 ty2
431 genUsgCmpTy cmp ty1 (NoteTy (FTVNote _) ty2)
432 = genUsgCmpTy cmp ty1 ty2
434 genUsgCmpTy cmp (TyVarTy _) (TyVarTy _)
437 genUsgCmpTy cmp (AppTy tya1 tyb1) (AppTy tya2 tyb2)
438 = unionUCSs [genUsgCmpTy cmp tya1 tya2,
439 genUsgCmpTy cmp tyb1 tyb2, -- note, *both* ways for arg, since fun (prob) unknown
440 genUsgCmpTy cmp tyb2 tyb1]
442 genUsgCmpTy cmp (TyConApp tc1 ty1s) (TyConApp tc2 ty2s)
443 = case tyConArgVrcs_maybe tc1 of
444 Just oi -> unionUCSs (zipWith3 (\ ty1 ty2 (occPos,occNeg) ->
445 -- strictly this is wasteful (and possibly dangerous) for
446 -- usgEqTy, but I think it's OK. KSW 1999-04.
447 (if occPos then genUsgCmpTy cmp ty1 ty2 else emptyUConSet)
449 (if occNeg then genUsgCmpTy cmp ty2 ty1 else emptyUConSet))
451 Nothing -> panic ("genUsgCmpTy: variance info unavailable for " ++ showSDoc (ppr tc1))
453 genUsgCmpTy cmp (FunTy tya1 tyb1) (FunTy tya2 tyb2)
454 = genUsgCmpTy cmp tya2 tya1 `unionUCS` genUsgCmpTy cmp tyb1 tyb2 -- contravariance of arrow
456 genUsgCmpTy cmp (ForAllTy _ ty1) (ForAllTy _ ty2)
457 = genUsgCmpTy cmp ty1 ty2
459 genUsgCmpTy cmp ty1 ty2
460 = pprPanic "genUsgCmpTy: type shapes don't match" $
461 vcat [ppr ty1, ppr ty2]
465 Applying a substitution to all @UVar@s. This also moves @TermUsg@
466 notes on lambdas into the @lbvarInfo@ field of the binder. This
467 latter is a hack. KSW 1999-04.
470 appUSubstTy :: (UVar -> UsageAnn)
474 appUSubstTy s (NoteTy (UsgNote (UsVar uv)) ty)
475 = mkUsgTy (s uv) (appUSubstTy s ty)
476 appUSubstTy s (NoteTy note@(UsgNote _) ty) = NoteTy note (appUSubstTy s ty)
477 appUSubstTy s (NoteTy note@(SynNote _) ty) = NoteTy note (appUSubstTy s ty)
478 appUSubstTy s (NoteTy note@(FTVNote _) ty) = NoteTy note (appUSubstTy s ty)
479 appUSubstTy s ty@(TyVarTy _) = ty
480 appUSubstTy s (AppTy ty1 ty2) = AppTy (appUSubstTy s ty1) (appUSubstTy s ty2)
481 appUSubstTy s (TyConApp tc tys) = TyConApp tc (map (appUSubstTy s) tys)
482 appUSubstTy s (FunTy ty1 ty2) = FunTy (appUSubstTy s ty1) (appUSubstTy s ty2)
483 appUSubstTy s (ForAllTy tyv ty) = ForAllTy tyv (appUSubstTy s ty)
486 appUSubstBinds :: (UVar -> UsageAnn)
490 appUSubstBinds s binds = fst $ initAnnotM () $
491 genAnnotBinds mungeType mungeTerm binds
492 where mungeType _ ty = -- simply perform substitution
493 return (appUSubstTy s ty)
495 mungeTerm (Note (TermUsg (UsVar uv)) (Lam v e))
496 -- perform substitution *and* munge annot on lambda into IdInfo.lbvarInfo
497 = let lb = case (s uv) of { UsOnce -> IsOneShotLambda; UsMany -> NoLBVarInfo }
498 v' = modifyIdInfo (`setLBVarInfo` lb) v -- HACK ALERT!
499 -- see comment in IdInfo.lhs; this is because the info is easier to
500 -- access here, by agreement SLPJ/KSW 1999-04 (as a "short-term hack").
502 -- really should be: return (Note (TermUsg (s uv)) (Lam v e))
503 mungeTerm e@(Lam _ _) = return e
504 mungeTerm e = panic "appUSubstBinds: mungeTerm:" (ppr e)
508 A @VarMultiset@ is what it says: a set of variables with counts
509 attached to them. We build one out of a @VarEnv@.
512 type VarMultiset = VarEnv (IdOrTyVar,Int) -- I guess 536 870 911 occurrences is enough
514 emptyMS = emptyVarEnv
515 unitMS v = unitVarEnv v (v,1)
516 delFromMS = delVarEnv
517 plusMS :: VarMultiset -> VarMultiset -> VarMultiset
518 plusMS = plusVarEnv_C (\ (v,n) (_,m) -> (v,n+m))
519 maxMS :: VarMultiset -> VarMultiset -> VarMultiset
520 maxMS = plusVarEnv_C (\ (v,n) (_,m) -> (v,max n m))
521 mapMS f = mapVarEnv (\ (v,n) -> f v n)
522 foldMS f = foldVarEnv (\ (v,n) a -> f v n a)
523 occInMS v ms = case lookupVarEnv ms v of
528 And a function used in debugging. It may give false positives with -DUSMANY turned off.
531 isUnAnnotated :: Type -> Bool
533 isUnAnnotated (NoteTy (UsgNote _ ) _ ) = False
534 isUnAnnotated (NoteTy (SynNote sty) ty) = isUnAnnotated sty && isUnAnnotated ty
535 isUnAnnotated (NoteTy (FTVNote _ ) ty) = isUnAnnotated ty
536 isUnAnnotated (TyVarTy _) = True
537 isUnAnnotated (AppTy ty1 ty2) = isUnAnnotated ty1 && isUnAnnotated ty2
538 isUnAnnotated (TyConApp tc tys) = all isUnAnnotated tys
539 isUnAnnotated (FunTy ty1 ty2) = isUnAnnotated ty1 && isUnAnnotated ty2
540 isUnAnnotated (ForAllTy tyv ty) = isUnAnnotated ty
543 ======================================================================