2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
5 \section[Id]{@Ids@: Value and constructor identifiers}
10 -- GHC uses several kinds of name internally:
12 -- * 'OccName.OccName': see "OccName#name_types"
14 -- * 'RdrName.RdrName': see "RdrName#name_types"
16 -- * 'Name.Name': see "Name#name_types"
18 -- * 'Id.Id' represents names that not only have a 'Name.Name' but also a 'TypeRep.Type' and some additional
19 -- details (a 'IdInfo.IdInfo' and one of 'Var.LocalIdDetails' or 'IdInfo.GlobalIdDetails') that
20 -- are added, modified and inspected by various compiler passes. These 'Var.Var' names may either
21 -- be global or local, see "Var#globalvslocal"
23 -- * 'Var.Var': see "Var#name_types"
28 -- ** Simple construction
29 mkGlobalId, mkVanillaGlobal, mkVanillaGlobalWithInfo,
30 mkLocalId, mkLocalIdWithInfo,
31 mkSysLocal, mkSysLocalM, mkUserLocal, mkUserLocalM,
32 mkTemplateLocals, mkTemplateLocalsNum, mkWildId, mkTemplateLocal,
33 mkWorkerId, mkExportedLocalId,
35 -- ** Taking an Id apart
36 idName, idType, idUnique, idInfo,
37 isId, globalIdDetails, idPrimRep,
38 recordSelectorFieldLabel,
41 setIdName, setIdUnique, Id.setIdType, setIdExported, setIdNotExported,
42 globaliseId, setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
43 zapLamIdInfo, zapDemandIdInfo, zapFragileIdInfo, transferPolyIdInfo,
45 -- ** Predicates on Ids
46 isImplicitId, isDeadBinder, isDictId, isStrictId,
47 isExportedId, isLocalId, isGlobalId,
48 isRecordSelector, isNaughtyRecordSelector,
50 isPrimOpId, isPrimOpId_maybe,
51 isFCallId, isFCallId_maybe,
52 isDataConWorkId, isDataConWorkId_maybe, isDataConId_maybe, idDataCon,
53 isBottomingId, idIsFrom,
54 isTickBoxOp, isTickBoxOp_maybe,
57 -- ** Inline pragma stuff
58 idInlinePragma, setInlinePragma, modifyInlinePragma,
60 -- ** One-shot lambdas
61 isOneShotBndr, isOneShotLambda, isStateHackType,
62 setOneShotLambda, clearOneShotLambda,
64 -- ** Reading 'IdInfo' fields
66 idNewDemandInfo, idNewDemandInfo_maybe,
67 idNewStrictness, idNewStrictness_maybe,
70 idSpecialisation, idCoreRules, idHasRules,
81 -- ** Writing 'IdInfo' fields
85 setIdNewStrictness, zapIdNewStrictness,
98 #include "HsVersions.h"
100 import CoreSyn ( CoreRule, Unfolding )
110 #ifdef OLD_STRICTNESS
111 import qualified Demand
129 -- infixl so you can say (id `set` a `set` b)
130 infixl 1 `setIdUnfolding`,
132 `setIdNewDemandInfo`,
133 `setIdNewStrictness`,
135 `setIdSpecialisation`,
138 #ifdef OLD_STRICTNESS
145 %************************************************************************
147 \subsection{Basic Id manipulation}
149 %************************************************************************
155 idUnique :: Id -> Unique
161 idInfo :: Id -> IdInfo
164 idPrimRep :: Id -> PrimRep
165 idPrimRep id = typePrimRep (idType id)
167 globalIdDetails :: Id -> GlobalIdDetails
168 globalIdDetails = globalIdVarDetails
171 setIdName :: Id -> Name -> Id
172 setIdName = setVarName
174 setIdUnique :: Id -> Unique -> Id
175 setIdUnique = setVarUnique
177 -- | Not only does this set the 'Id' 'Type', it also evaluates the type to try and
178 -- reduce space usage
179 setIdType :: Id -> Type -> Id
180 setIdType id ty = seqType ty `seq` Var.setVarType id ty
182 setIdExported :: Id -> Id
183 setIdExported = setIdVarExported
185 setIdNotExported :: Id -> Id
186 setIdNotExported = setIdVarNotExported
188 globaliseId :: GlobalIdDetails -> Id -> Id
189 globaliseId = globaliseIdVar
191 lazySetIdInfo :: Id -> IdInfo -> Id
192 lazySetIdInfo = lazySetVarIdInfo
194 setIdInfo :: Id -> IdInfo -> Id
195 setIdInfo id info = seqIdInfo info `seq` (lazySetIdInfo id info)
196 -- Try to avoid spack leaks by seq'ing
198 modifyIdInfo :: (IdInfo -> IdInfo) -> Id -> Id
199 modifyIdInfo fn id = setIdInfo id (fn (idInfo id))
201 -- maybeModifyIdInfo tries to avoid unnecesary thrashing
202 maybeModifyIdInfo :: Maybe IdInfo -> Id -> Id
203 maybeModifyIdInfo (Just new_info) id = lazySetIdInfo id new_info
204 maybeModifyIdInfo Nothing id = id
207 %************************************************************************
209 \subsection{Simple Id construction}
211 %************************************************************************
213 Absolutely all Ids are made by mkId. It is just like Var.mkId,
214 but in addition it pins free-tyvar-info onto the Id's type,
215 where it can easily be found.
217 Note [Free type variables]
218 ~~~~~~~~~~~~~~~~~~~~~~~~~~
219 At one time we cached the free type variables of the type of an Id
220 at the root of the type in a TyNote. The idea was to avoid repeating
221 the free-type-variable calculation. But it turned out to slow down
222 the compiler overall. I don't quite know why; perhaps finding free
223 type variables of an Id isn't all that common whereas applying a
224 substitution (which changes the free type variables) is more common.
225 Anyway, we removed it in March 2008.
228 -- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
229 mkGlobalId :: GlobalIdDetails -> Name -> Type -> IdInfo -> Id
230 mkGlobalId = mkGlobalIdVar
232 -- | Make a global 'Id' without any extra information at all
233 mkVanillaGlobal :: Name -> Type -> Id
234 mkVanillaGlobal name ty = mkVanillaGlobalWithInfo name ty vanillaIdInfo
236 -- | Make a global 'Id' with no global information but some generic 'IdInfo'
237 mkVanillaGlobalWithInfo :: Name -> Type -> IdInfo -> Id
238 mkVanillaGlobalWithInfo = mkGlobalId VanillaGlobal
241 -- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
242 mkLocalId :: Name -> Type -> Id
243 mkLocalId name ty = mkLocalIdWithInfo name ty vanillaIdInfo
245 mkLocalIdWithInfo :: Name -> Type -> IdInfo -> Id
246 mkLocalIdWithInfo = mkLocalIdVar
247 -- Note [Free type variables]
249 -- | Create a local 'Id' that is marked as exported. This prevents things attached to it from being removed as dead code.
250 mkExportedLocalId :: Name -> Type -> Id
251 mkExportedLocalId name ty = mkExportedLocalIdVar name ty vanillaIdInfo
252 -- Note [Free type variables]
255 -- | Create a system local 'Id'. These are local 'Id's (see "Var#globalvslocal") that are created by the compiler out of thin air
256 mkSysLocal :: FastString -> Unique -> Type -> Id
257 mkSysLocal fs uniq ty = mkLocalId (mkSystemVarName uniq fs) ty
259 mkSysLocalM :: MonadUnique m => FastString -> Type -> m Id
260 mkSysLocalM fs ty = getUniqueM >>= (\uniq -> return (mkSysLocal fs uniq ty))
263 -- | Create a user local 'Id'. These are local 'Id's (see "Var#globalvslocal") with a name and location that the user might recognize
264 mkUserLocal :: OccName -> Unique -> Type -> SrcSpan -> Id
265 mkUserLocal occ uniq ty loc = mkLocalId (mkInternalName uniq occ loc) ty
267 mkUserLocalM :: MonadUnique m => OccName -> Type -> SrcSpan -> m Id
268 mkUserLocalM occ ty loc = getUniqueM >>= (\uniq -> return (mkUserLocal occ uniq ty loc))
272 Make some local @Ids@ for a template @CoreExpr@. These have bogus
273 @Uniques@, but that's OK because the templates are supposed to be
274 instantiated before use.
277 -- | Make a /wild Id/. This is typically used when you need a binder that you don't expect to use
278 mkWildId :: Type -> Id
279 mkWildId ty = mkSysLocal (fsLit "wild") (mkBuiltinUnique 1) ty
281 -- | Workers get local names. "CoreTidy" will externalise these if necessary
282 mkWorkerId :: Unique -> Id -> Type -> Id
283 mkWorkerId uniq unwrkr ty
284 = mkLocalId wkr_name ty
286 wkr_name = mkInternalName uniq (mkWorkerOcc (getOccName unwrkr)) (getSrcSpan unwrkr)
288 -- | Create a /template local/: a family of system local 'Id's in bijection with @Int@s, typically used in unfoldings
289 mkTemplateLocal :: Int -> Type -> Id
290 mkTemplateLocal i ty = mkSysLocal (fsLit "tpl") (mkBuiltinUnique i) ty
292 -- | Create a template local for a series of types
293 mkTemplateLocals :: [Type] -> [Id]
294 mkTemplateLocals = mkTemplateLocalsNum 1
296 -- | Create a template local for a series of type, but start from a specified template local
297 mkTemplateLocalsNum :: Int -> [Type] -> [Id]
298 mkTemplateLocalsNum n tys = zipWith mkTemplateLocal [n..] tys
302 %************************************************************************
304 \subsection{Basic predicates on @Id@s}
306 %************************************************************************
312 -- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
313 isLocalId :: Id -> Bool
314 isLocalId = isLocalIdVar
316 -- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
317 isGlobalId :: Id -> Bool
318 isGlobalId = isGlobalIdVar
320 -- | Determines whether an 'Id' is marked as exported and hence will not be considered dead code
321 isExportedId :: Id -> Bool
322 isExportedId = isExportedIdVar
325 %************************************************************************
327 \subsection{Special Ids}
329 %************************************************************************
332 -- | If the 'Id' is that for a record selector, extract the 'sel_tycon' and label. Panic otherwise
333 recordSelectorFieldLabel :: Id -> (TyCon, FieldLabel)
334 recordSelectorFieldLabel id
335 = case globalIdDetails id of
336 RecordSelId { sel_tycon = tycon, sel_label = lbl } -> (tycon,lbl)
337 _ -> panic "recordSelectorFieldLabel"
339 isRecordSelector :: Id -> Bool
340 isNaughtyRecordSelector :: Id -> Bool
341 isPrimOpId :: Id -> Bool
342 isFCallId :: Id -> Bool
343 isDataConWorkId :: Id -> Bool
345 isClassOpId_maybe :: Id -> Maybe Class
346 isPrimOpId_maybe :: Id -> Maybe PrimOp
347 isFCallId_maybe :: Id -> Maybe ForeignCall
348 isDataConWorkId_maybe :: Id -> Maybe DataCon
350 isRecordSelector id = case globalIdDetails id of
351 RecordSelId {} -> True
354 isNaughtyRecordSelector id = case globalIdDetails id of
355 RecordSelId { sel_naughty = n } -> n
358 isClassOpId_maybe id = case globalIdDetails id of
359 ClassOpId cls -> Just cls
362 isPrimOpId id = case globalIdDetails id of
366 isPrimOpId_maybe id = case globalIdDetails id of
367 PrimOpId op -> Just op
370 isFCallId id = case globalIdDetails id of
374 isFCallId_maybe id = case globalIdDetails id of
375 FCallId call -> Just call
378 isDataConWorkId id = case globalIdDetails id of
379 DataConWorkId _ -> True
382 isDataConWorkId_maybe id = case globalIdDetails id of
383 DataConWorkId con -> Just con
386 isDataConId_maybe :: Id -> Maybe DataCon
387 isDataConId_maybe id = case globalIdDetails id of
388 DataConWorkId con -> Just con
389 DataConWrapId con -> Just con
392 idDataCon :: Id -> DataCon
393 -- ^ Get from either the worker or the wrapper 'Id' to the 'DataCon'. Currently used only in the desugarer.
395 -- INVARIANT: @idDataCon (dataConWrapId d) = d@: remember, 'dataConWrapId' can return either the wrapper or the worker
396 idDataCon id = isDataConId_maybe id `orElse` pprPanic "idDataCon" (ppr id)
399 isDictId :: Id -> Bool
400 isDictId id = isDictTy (idType id)
402 hasNoBinding :: Id -> Bool
403 -- ^ Returns @True@ of an 'Id' which may not have a
404 -- binding, even though it is defined in this module.
406 -- Data constructor workers used to be things of this kind, but
407 -- they aren't any more. Instead, we inject a binding for
408 -- them at the CorePrep stage.
409 -- EXCEPT: unboxed tuples, which definitely have no binding
410 hasNoBinding id = case globalIdDetails id of
411 PrimOpId _ -> True -- See Note [Primop wrappers]
413 DataConWorkId dc -> isUnboxedTupleCon dc
416 isImplicitId :: Id -> Bool
417 -- ^ 'isImplicitId' tells whether an 'Id's info is implied by other
418 -- declarations, so we don't need to put its signature in an interface
419 -- file, even if it's mentioned in some other interface unfolding.
421 = case globalIdDetails id of
422 RecordSelId {} -> True
426 DataConWorkId _ -> True
427 DataConWrapId _ -> True
428 -- These are are implied by their type or class decl;
429 -- remember that all type and class decls appear in the interface file.
430 -- The dfun id is not an implicit Id; it must *not* be omitted, because
431 -- it carries version info for the instance decl
434 idIsFrom :: Module -> Id -> Bool
435 idIsFrom mod id = nameIsLocalOrFrom mod (idName id)
438 Note [Primop wrappers]
439 ~~~~~~~~~~~~~~~~~~~~~~
440 Currently hasNoBinding claims that PrimOpIds don't have a curried
441 function definition. But actually they do, in GHC.PrimopWrappers,
442 which is auto-generated from prelude/primops.txt.pp. So actually, hasNoBinding
443 could return 'False' for PrimOpIds.
445 But we'd need to add something in CoreToStg to swizzle any unsaturated
446 applications of GHC.Prim.plusInt# to GHC.PrimopWrappers.plusInt#.
448 Nota Bene: GHC.PrimopWrappers is needed *regardless*, because it's
449 used by GHCi, which does not implement primops direct at all.
454 isDeadBinder :: Id -> Bool
455 isDeadBinder bndr | isId bndr = isDeadOcc (idOccInfo bndr)
456 | otherwise = False -- TyVars count as not dead
460 isTickBoxOp :: Id -> Bool
462 case globalIdDetails id of
463 TickBoxOpId _ -> True
466 isTickBoxOp_maybe :: Id -> Maybe TickBoxOp
467 isTickBoxOp_maybe id =
468 case globalIdDetails id of
469 TickBoxOpId tick -> Just tick
473 %************************************************************************
475 \subsection{IdInfo stuff}
477 %************************************************************************
480 ---------------------------------
482 idArity :: Id -> Arity
483 idArity id = arityInfo (idInfo id)
485 setIdArity :: Id -> Arity -> Id
486 setIdArity id arity = modifyIdInfo (`setArityInfo` arity) id
488 #ifdef OLD_STRICTNESS
489 ---------------------------------
491 idStrictness :: Id -> StrictnessInfo
492 idStrictness id = strictnessInfo (idInfo id)
494 setIdStrictness :: Id -> StrictnessInfo -> Id
495 setIdStrictness id strict_info = modifyIdInfo (`setStrictnessInfo` strict_info) id
498 -- | Returns true if an application to n args would diverge
499 isBottomingId :: Id -> Bool
500 isBottomingId id = isBottomingSig (idNewStrictness id)
502 idNewStrictness_maybe :: Id -> Maybe StrictSig
503 idNewStrictness :: Id -> StrictSig
505 idNewStrictness_maybe id = newStrictnessInfo (idInfo id)
506 idNewStrictness id = idNewStrictness_maybe id `orElse` topSig
508 setIdNewStrictness :: Id -> StrictSig -> Id
509 setIdNewStrictness id sig = modifyIdInfo (`setNewStrictnessInfo` Just sig) id
511 zapIdNewStrictness :: Id -> Id
512 zapIdNewStrictness id = modifyIdInfo (`setNewStrictnessInfo` Nothing) id
514 -- | This predicate says whether the 'Id' has a strict demand placed on it or
515 -- has a type such that it can always be evaluated strictly (e.g., an
516 -- unlifted type, but see the comment for 'isStrictType'). We need to
517 -- check separately whether the 'Id' has a so-called \"strict type\" because if
518 -- the demand for the given @id@ hasn't been computed yet but @id@ has a strict
519 -- type, we still want @isStrictId id@ to be @True@.
520 isStrictId :: Id -> Bool
522 = ASSERT2( isId id, text "isStrictId: not an id: " <+> ppr id )
523 (isStrictDmd (idNewDemandInfo id)) ||
524 (isStrictType (idType id))
526 ---------------------------------
528 idWorkerInfo :: Id -> WorkerInfo
529 idWorkerInfo id = workerInfo (idInfo id)
531 setIdWorkerInfo :: Id -> WorkerInfo -> Id
532 setIdWorkerInfo id work_info = modifyIdInfo (`setWorkerInfo` work_info) id
534 ---------------------------------
536 idUnfolding :: Id -> Unfolding
537 idUnfolding id = unfoldingInfo (idInfo id)
539 setIdUnfolding :: Id -> Unfolding -> Id
540 setIdUnfolding id unfolding = modifyIdInfo (`setUnfoldingInfo` unfolding) id
542 #ifdef OLD_STRICTNESS
543 ---------------------------------
545 idDemandInfo :: Id -> Demand.Demand
546 idDemandInfo id = demandInfo (idInfo id)
548 setIdDemandInfo :: Id -> Demand.Demand -> Id
549 setIdDemandInfo id demand_info = modifyIdInfo (`setDemandInfo` demand_info) id
552 idNewDemandInfo_maybe :: Id -> Maybe NewDemand.Demand
553 idNewDemandInfo :: Id -> NewDemand.Demand
555 idNewDemandInfo_maybe id = newDemandInfo (idInfo id)
556 idNewDemandInfo id = newDemandInfo (idInfo id) `orElse` NewDemand.topDmd
558 setIdNewDemandInfo :: Id -> NewDemand.Demand -> Id
559 setIdNewDemandInfo id dmd = modifyIdInfo (`setNewDemandInfo` Just dmd) id
561 ---------------------------------
563 idSpecialisation :: Id -> SpecInfo
564 idSpecialisation id = specInfo (idInfo id)
566 idCoreRules :: Id -> [CoreRule]
567 idCoreRules id = specInfoRules (idSpecialisation id)
569 idHasRules :: Id -> Bool
570 idHasRules id = not (isEmptySpecInfo (idSpecialisation id))
572 setIdSpecialisation :: Id -> SpecInfo -> Id
573 setIdSpecialisation id spec_info = modifyIdInfo (`setSpecInfo` spec_info) id
575 ---------------------------------
577 idCafInfo :: Id -> CafInfo
578 #ifdef OLD_STRICTNESS
579 idCafInfo id = case cgInfo (idInfo id) of
580 NoCgInfo -> pprPanic "idCafInfo" (ppr id)
581 info -> cgCafInfo info
583 idCafInfo id = cafInfo (idInfo id)
586 setIdCafInfo :: Id -> CafInfo -> Id
587 setIdCafInfo id caf_info = modifyIdInfo (`setCafInfo` caf_info) id
589 ---------------------------------
591 #ifdef OLD_STRICTNESS
592 idCprInfo :: Id -> CprInfo
593 idCprInfo id = cprInfo (idInfo id)
595 setIdCprInfo :: Id -> CprInfo -> Id
596 setIdCprInfo id cpr_info = modifyIdInfo (`setCprInfo` cpr_info) id
599 ---------------------------------
601 idOccInfo :: Id -> OccInfo
602 idOccInfo id = occInfo (idInfo id)
604 setIdOccInfo :: Id -> OccInfo -> Id
605 setIdOccInfo id occ_info = modifyIdInfo (`setOccInfo` occ_info) id
609 ---------------------------------
611 The inline pragma tells us to be very keen to inline this Id, but it's still
612 OK not to if optimisation is switched off.
615 idInlinePragma :: Id -> InlinePragInfo
616 idInlinePragma id = inlinePragInfo (idInfo id)
618 setInlinePragma :: Id -> InlinePragInfo -> Id
619 setInlinePragma id prag = modifyIdInfo (`setInlinePragInfo` prag) id
621 modifyInlinePragma :: Id -> (InlinePragInfo -> InlinePragInfo) -> Id
622 modifyInlinePragma id fn = modifyIdInfo (\info -> info `setInlinePragInfo` (fn (inlinePragInfo info))) id
626 ---------------------------------
629 idLBVarInfo :: Id -> LBVarInfo
630 idLBVarInfo id = lbvarInfo (idInfo id)
632 -- | Returns whether the lambda associated with the 'Id' is certainly applied at most once
633 -- OR we are applying the \"state hack\" which makes it appear as if theis is the case for
634 -- lambdas used in @IO@. You should prefer using this over 'isOneShotLambda'
635 isOneShotBndr :: Id -> Bool
636 -- This one is the "business end", called externally.
637 -- Its main purpose is to encapsulate the Horrible State Hack
638 isOneShotBndr id = isOneShotLambda id || isStateHackType (idType id)
640 -- | Should we apply the state hack to values of this 'Type'?
641 isStateHackType :: Type -> Bool
646 = case splitTyConApp_maybe ty of
647 Just (tycon,_) -> tycon == statePrimTyCon
649 -- This is a gross hack. It claims that
650 -- every function over realWorldStatePrimTy is a one-shot
651 -- function. This is pretty true in practice, and makes a big
652 -- difference. For example, consider
653 -- a `thenST` \ r -> ...E...
654 -- The early full laziness pass, if it doesn't know that r is one-shot
655 -- will pull out E (let's say it doesn't mention r) to give
656 -- let lvl = E in a `thenST` \ r -> ...lvl...
657 -- When `thenST` gets inlined, we end up with
658 -- let lvl = E in \s -> case a s of (r, s') -> ...lvl...
659 -- and we don't re-inline E.
661 -- It would be better to spot that r was one-shot to start with, but
662 -- I don't want to rely on that.
664 -- Another good example is in fill_in in PrelPack.lhs. We should be able to
665 -- spot that fill_in has arity 2 (and when Keith is done, we will) but we can't yet.
668 -- | Returns whether the lambda associated with the 'Id' is certainly applied at most once.
669 -- You probably want to use 'isOneShotBndr' instead
670 isOneShotLambda :: Id -> Bool
671 isOneShotLambda id = case idLBVarInfo id of
672 IsOneShotLambda -> True
675 setOneShotLambda :: Id -> Id
676 setOneShotLambda id = modifyIdInfo (`setLBVarInfo` IsOneShotLambda) id
678 clearOneShotLambda :: Id -> Id
679 clearOneShotLambda id
680 | isOneShotLambda id = modifyIdInfo (`setLBVarInfo` NoLBVarInfo) id
683 -- The OneShotLambda functions simply fiddle with the IdInfo flag
684 -- But watch out: this may change the type of something else
686 -- If we change the one-shot-ness of x, f's type changes
690 zapInfo :: (IdInfo -> Maybe IdInfo) -> Id -> Id
691 zapInfo zapper id = maybeModifyIdInfo (zapper (idInfo id)) id
693 zapLamIdInfo :: Id -> Id
694 zapLamIdInfo = zapInfo zapLamInfo
696 zapDemandIdInfo :: Id -> Id
697 zapDemandIdInfo = zapInfo zapDemandInfo
699 zapFragileIdInfo :: Id -> Id
700 zapFragileIdInfo = zapInfo zapFragileInfo
703 Note [transferPolyIdInfo]
704 ~~~~~~~~~~~~~~~~~~~~~~~~~
707 f = /\a. let g = rhs in ...
709 where g has interesting strictness information. Then if we float thus
714 we *do not* want to lose the strictness information on g. Nor arity.
716 It's simple to retain strictness and arity, but not so simple to retain
719 so we simply discard those. Sooner or later this may bite us.
721 This transfer is used in two places:
722 FloatOut (long-distance let-floating)
723 SimplUtils.abstractFloats (short-distance let-floating)
726 transferPolyIdInfo :: Id -> Id -> Id
727 transferPolyIdInfo old_id new_id
728 = modifyIdInfo transfer new_id
730 old_info = idInfo old_id
731 transfer new_info = new_info `setNewStrictnessInfo` (newStrictnessInfo old_info)
732 `setArityInfo` (arityInfo old_info)