pub struct Core {
pub kind: CoreKind,
pub ty: Ty,
pub tier: Tier,
pub span: Span,
pub last_use: bool,
pub order: u32,
pub locals: u32,
}Fields§
§kind: CoreKind§ty: Ty§tier: TierWhich tier this node runs on. §4.2: “explicit tier annotation per node”.
span: Span§last_use: boolSet on a CoreKind::Var whose value this expression is the last reader of, so a
backend may move the binding rather than copy it. crate::liveness is what sets it and
what the guarantee means; false is always safe.
order: u32Set on a CoreKind::Make: which written field belongs at each position of the record it
builds, packed four bits per field. crate::fields is what sets it and what the packing
means; crate::fields::UNORDERED is always safe and means “sort at run time”.
It costs nothing: a u32 here fits in the padding last_use already leaves, so Core is
160 bytes either way.
locals: u32Set on a CoreKind::Lam: how many bindings its body makes, so a call can reserve room
for them in one frame instead of allocating a scope per let. crate::frames is what
sets it and what the count means; 0 is always safe and means “chain a scope, as before”.
Implementations§
Source§impl Core
impl Core
pub fn new(kind: CoreKind, ty: Ty, span: Span) -> Core
Sourcepub fn effects(
&self,
globals: &dyn Fn(&str) -> Vec<Effect>,
out: &mut Vec<Effect>,
)
pub fn effects( &self, globals: &dyn Fn(&str) -> Vec<Effect>, out: &mut Vec<Effect>, )
Every effect this expression can perform, by walking what it calls.
Phase 1 used this as the effect analysis. Phase 2 does not: rows are inferred during checking, where a call’s latent row is known and a mere reference to a function performs nothing. What survives is this syntactic over-approximation, used in one place where that is the right answer — asking what a fold’s function body could reach, including through a function value it was handed.