Skip to main content

cove_ir/lower/
mod.rs

1//! Turning a checked package into the executable IR.
2//!
3//! This reads the answers `cove-sema` already settled and writes them down
4//! as slots and instructions. It re-derives nothing: an expression's type
5//! comes from [`Facts::ty`](cove_sema::Facts::ty), a declaration's boundary
6//! from [`Facts::signature`](cove_sema::Facts::signature), and where the two
7//! could disagree the checker is right by construction because this asked it
8//! rather than working it out again.
9//!
10//! # There is no refusal
11//!
12//! A valid checked program lowers. That is the whole contract, and it is
13//! what [ADR 0034](../../../../docs/adr/0034-one-physical-word-stack.md)
14//! replaces the predecessor's admission predicate with. The two ways this
15//! can answer `Err` are the two `gap` module builds — an unsettled type and
16//! a construct this crate has not been taught yet — and neither is a
17//! judgement about the program.
18//!
19//! # A value is a run of words, and the lowering is what knows how many
20//!
21//! `docs/LINEAR_VM.md` puts the fields of a struct where the value is, so
22//! `l.from.x` is a slot number this module computes and not an instruction
23//! the machine runs. A field access on an inline value is *arithmetic on a
24//! slot*, and only a field of a heap object is a load. That is why
25//! `Val` is a base slot and a layout rather than a slot and a `Repr`: the
26//! layout is what a copy's width, a location's reference words and a field's
27//! offset are all read off.
28//!
29//! # A generic is one function per instantiation
30//!
31//! `docs/LINEAR_VM.md` says why there was no choice: a slot's `Repr` is fixed
32//! for the whole function, that is what makes one static reference map
33//! correct at every program counter, and a generic value's width is a fact
34//! about the type argument — `Cell<Int>` is one word and `Cell<Point>` is
35//! two. Carrying layouts at run time would make widths dynamic and take the
36//! map with them; boxing every generic value would allocate on `f(1)` and
37//! make a type parameter mean what `dyn Trait` already means. So `f<Int>` and
38//! `f<Point>` are two functions and two frames, and a generic `struct` at two
39//! instantiations is two layouts.
40//!
41//! It costs one substitution and no second walk. The checker walked the
42//! generic body once with its type parameters rigid, so every fact in it is
43//! recorded in terms of them, and `Body::ty` completes one as it is read.
44//! Which arguments a call site asks for is read off the facts the checker
45//! settled there — `Body::instantiation` is that reading, and it is also why
46//! an explicit type argument needs no path of its own: the checker applied
47//! it before this crate saw anything.
48//!
49//! # The shape of a lowered body
50//!
51//! Control flow is flat. There are no basic blocks and no block arguments:
52//! an `if` is a [`Inst::BranchFalse`] over a run of instructions, a `while`
53//! is a backward [`Inst::Jump`], and both are emitted with an unpatchable
54//! target that is filled in once the destination is known. A loop keeps the
55//! jumps its `break`s left behind and patches them when it learns where its
56//! end is.
57//!
58//! Every function ends in [`Inst::Return`], and it is emitted
59//! unconditionally — even after a body that already returned on every path.
60//! That is one dead word, and what it buys is that every patched target
61//! lands on an instruction: a branch whose destination is "after everything"
62//! has something to be after. Tracking reachability well enough to drop it
63//! would mean tracking which pending patches point past the end, which is
64//! more machinery than the word is worth.
65
66mod assertions;
67mod cells;
68mod closures;
69mod collections;
70mod dispatch;
71mod dropping;
72mod expr;
73mod frame;
74mod frees;
75mod gap;
76mod inline;
77mod limits;
78mod methods;
79mod pattern;
80mod shapes;
81mod stmt;
82mod tails;
83mod tasks;
84mod walks;
85
86#[cfg(test)]
87mod tests;
88
89use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
90use std::sync::Arc;
91
92use cove_diag::{Diagnostic, SourceMap, Span};
93use cove_schema::HostSchemas;
94use cove_sema::facts::MethodTarget;
95use cove_sema::resolve::{FnKey, Node, Program as Checked};
96use cove_sema::typeck::Ty;
97use cove_syntax::ast::{Expr, FnDecl};
98
99use crate::inst::{Inst, Pc, Slot};
100use crate::layout::LayoutId;
101use crate::program::{
102    Arg, ArgsId, Builtin, BuiltinId, Function, FunctionId, HostOp, HostOpId, Program, StrId, Table,
103    TableId,
104};
105use crate::repr::{RefMap, Repr};
106
107use frame::{Frame, Val};
108use shapes::Shapes;
109
110/// The target of a jump that has been emitted but whose destination is not
111/// known yet.
112///
113/// `u32::MAX` rather than `0`, so that a patch this lowering forgot is a
114/// verifier fault naming the instruction rather than a silent jump to the
115/// top of the function.
116const PENDING: Pc = Pc::MAX;
117
118/// Where a form assembles its answer: a base slot and the layout that says
119/// how wide it is.
120///
121/// A destination is a *location*, not a slot, because a value may be several
122/// words and both a branch join and a block tail have to write all of them.
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub(crate) struct Dest {
125    pub slot: Slot,
126    pub layout: LayoutId,
127}
128
129impl Dest {
130    fn of(val: &Val) -> Dest {
131        Dest {
132            slot: val.slot,
133            layout: val.layout,
134        }
135    }
136}
137
138/// Lowers a checked package: every declaration it has, whether or not
139/// anything reaches it.
140///
141/// The result either runs or names what stopped it. Nothing in between: a
142/// lowered [`Program`] has been through [`crate::verify()`], so a caller that
143/// holds one holds a program whose locations, jumps and calls are all in
144/// range and whose reference map is the one its reprs imply.
145///
146/// `sources` is the package's own text, and it is here for one reason:
147/// `assert` and `assertEqual` quote the code that failed, so the lowering
148/// has to read the bytes an argument's span covers. See this module's
149/// `assertions` submodule for why they are lowered rather than performed.
150///
151/// `schemas` is the set of host modules this compilation was given, and it
152/// must be the set the *checker* was given. A type a host module declares has
153/// a layout — a `files.Reader` is one [`Repr::Host`] word and an
154/// `http.Response` is its fields inline — and the schema is the only thing
155/// that says which of the two a name is. Reading `cove_schema::hosts` here
156/// instead would describe the shipped modules and no others, so a program
157/// that names a type an embedding registered would lower for fewer types than
158/// it checked against: a backend refusing a program the language admits,
159/// rather than a gap somebody can build. `HostApi` is a trait, and an
160/// embedder's module is not a lesser kind of host.
161///
162/// [`lower_roots`] is the same lowering over what a named set of roots
163/// reaches, and it is what a command that runs a program should use — a
164/// command names the roots it is about to run and this crate works out the
165/// slice. This one is what a whole-package listing means — everything the
166/// package declares is part of it — and it is what the lowering's own tests
167/// and the corpus survey ask for.
168pub fn lower(
169    checked: &Checked,
170    sources: &SourceMap,
171    schemas: &HostSchemas,
172) -> Result<Program, Vec<Diagnostic>> {
173    let mut plan = Plan::index(checked);
174    let everything: HashSet<FunctionId> = (0..plan.decls.len())
175        .map(|at| FunctionId(at as u32))
176        .collect();
177    let Lowering {
178        program, errors, ..
179    } = emit(checked, sources, schemas, &mut plan, &everything);
180    finish(program, errors)
181}
182
183/// Lowers only the declarations `roots` can reach.
184///
185/// A package holds programs that have nothing to do with each other —
186/// `benches/` is nine of them and `tests/e2e/` is a hundred — and a gap in
187/// one of them is not a reason to refuse the others. So a command lowers
188/// what it is about to run and leaves the rest as a stub nothing names.
189///
190/// A root is a `(module, name)` pair naming a declaration the way the
191/// checker's own tables do, and the slice is what *any* of them reaches.
192/// That is the whole of the API a command needs: it selects roots — the
193/// entry it was asked for, the test it is about to run, the entries a
194/// package configures — and reachability stays here. A caller that walked
195/// the call graph itself would be a second answer to a question this
196/// module already has to answer, and the two would drift.
197///
198/// A root that names nothing this package declares contributes nothing. It
199/// is not an error here, because what a name denotes is the checker's
200/// question and every caller has already asked it: `run_entry` answers
201/// "this package does not declare `m.f`" better than a lowering could, and
202/// it answers it about the program that was actually going to run.
203///
204/// # One answer for the whole set
205///
206/// The gaps this returns are the gaps of everything `roots` reaches,
207/// together, and there is no telling which root a gap came from. So a
208/// caller that needs one root's failure to be one root's failure passes
209/// one root — which is what [`lower_entry`] is, and why `cove test` lowers
210/// each test rather than the suite.
211///
212/// # What "reachable" is, and how this is sure of it
213///
214/// The seed is [`Program::call_graph`](cove_sema::resolve::Program::call_graph),
215/// which the checker already derived: for each declaration, every declaration
216/// it may call. Both precisions are followed, because
217/// [`CallPrecision::Approximate`](cove_sema::resolve::CallPrecision) is a
218/// superset of what may run and a slice has to hold everything that might.
219///
220/// The seed is not the answer, though, and the graph itself says why: a
221/// callee that is a *value* — `xs.map(double)`, a conformance a `dyn`
222/// dispatch picks, a `Snapshot` implementation nothing writes a call to —
223/// contributes no edge, because there is no call site naming it. A
224/// declaration missing from the slice is not a gap the person holding the
225/// source can act on; it is a stub that answers `()` where a call was meant
226/// to go.
227///
228/// So the slice is closed against the lowering rather than against the
229/// graph. Every place that turns a name into a [`FunctionId`] asks whether
230/// this pass lowered it first, and a body that names a declaration this
231/// slice left out records it rather than emitting a call to a stub. What was
232/// recorded is added to the slice and the package is lowered again,
233/// until a round wants nothing — which is a fixed point over *what this
234/// lowering emits references to*, not over what a second reachability
235/// analysis believes.
236///
237/// The call graph is what makes that one round rather than one per level of
238/// the call tree: seeded with nothing, each round could only discover the
239/// callees of what the round before it lowered.
240pub fn lower_roots(
241    checked: &Checked,
242    sources: &SourceMap,
243    schemas: &HostSchemas,
244    roots: &[(&str, &str)],
245) -> Result<Program, Vec<Diagnostic>> {
246    let mut plan = Plan::index(checked);
247    let mut reach = plan.reachable_from(checked, roots);
248    loop {
249        let Lowering {
250            program,
251            errors,
252            wanted,
253        } = emit(checked, sources, schemas, &mut plan, &reach);
254        if wanted.is_empty() {
255            return finish(program, errors);
256        }
257        reach.extend(wanted);
258    }
259}
260
261/// Lowers only the declarations `module.name` can reach.
262///
263/// The one-root case of [`lower_roots`], which is where everything this
264/// does is written down. It has a name of its own because one root is what
265/// almost every caller has — `cove run` has the entry it was asked for,
266/// `cove replay` has the entry the tape was recorded from, `cove test` has
267/// the test it is about to run — and because a set of one is the only set
268/// whose gaps belong to a single root.
269pub fn lower_entry(
270    checked: &Checked,
271    sources: &SourceMap,
272    schemas: &HostSchemas,
273    module: &str,
274    name: &str,
275) -> Result<Program, Vec<Diagnostic>> {
276    lower_roots(checked, sources, schemas, &[(module, name)])
277}
278
279/// One pass of the lowering over one set of declarations.
280struct Lowering {
281    program: Program,
282    errors: Vec<Diagnostic>,
283    /// The declarations a body named that this pass had left out.
284    ///
285    /// Empty for a whole-package lowering, because nothing is left out.
286    /// For a sliced one it is the correction: see [`lower_entry`].
287    wanted: HashSet<FunctionId>,
288}
289
290/// Lowers `reach` and stubs the rest.
291fn emit<'a>(
292    checked: &'a Checked,
293    sources: &SourceMap,
294    schemas: &HostSchemas,
295    plan: &mut Plan<'a>,
296    reach: &HashSet<FunctionId>,
297) -> Lowering {
298    let mut errors = Vec::new();
299    let mut wanted = HashSet::new();
300    let mut pool = Pool::new(schemas.clone());
301    plan.boundaries(checked, reach, &mut pool, &mut errors);
302    let mut functions = Vec::new();
303    for id in 0..plan.decls.len() {
304        functions.push(if reach.contains(&FunctionId(id as u32)) {
305            lower_function(
306                checked,
307                sources,
308                plan,
309                id,
310                &mut pool,
311                &mut errors,
312                &mut wanted,
313            )
314        } else {
315            stub(&plan.decls[id])
316        });
317    }
318    // A lambda and an instantiation are `Function`s of their own, numbered
319    // after every declaration and discovered while a body is being walked
320    // rather than by the plan. Either may be appended while the body that
321    // asked for it is still being lowered, so this list is complete only once
322    // the loop above has finished — which is why it is drained here and not
323    // built beside `plan.decls`.
324    functions.extend(
325        pool.appended
326            .drain(..)
327            .map(|held| held.expect("every reserved function was lowered into its own slot")),
328    );
329
330    let program = Program {
331        functions,
332        layouts: pool.shapes.into_table(),
333        str_layout: shapes::STR,
334        bytes_layout: shapes::BYTES,
335        buffer_layout: shapes::BYTE_BUFFER,
336        boxed_layout: shapes::BOXED,
337        strings: pool.strings,
338        args: pool.args.lists,
339        tables: pool.tables,
340        host_ops: pool.host_ops,
341        builtins: pool.builtins,
342        // Only what this pass lowered is nameable. A stub answers `()`, so
343        // an entry point that resolved to one would run and say nothing
344        // rather than saying it was not there — and `run_entry` already has
345        // a good answer for a name a program does not carry.
346        //
347        // A generic declaration is a stub for the same reason and is left out
348        // for the same reason. What a program carries is its
349        // instantiations — `f<Int>` — and there is no entry point among them:
350        // a command names a declaration, and which instantiation of a generic
351        // one it meant is not a question a command line can answer.
352        by_name: plan
353            .by_name
354            .iter()
355            .filter(|(_, id)| reach.contains(id))
356            .filter(|(_, id)| plan.decls[id.index()].decl.generics.is_empty())
357            .map(|(key, id)| (key.clone(), *id))
358            .collect(),
359    };
360    Lowering {
361        program,
362        errors,
363        wanted,
364    }
365}
366
367/// The lowered program, or what stopped it — and the verifier's word that
368/// the first of the two is well formed.
369fn finish(mut program: Program, errors: Vec<Diagnostic>) -> Result<Program, Vec<Diagnostic>> {
370    if !errors.is_empty() {
371        return Err(only_once(errors));
372    }
373
374    // A call to a small leaf is expanded where it is made, before the two
375    // passes below run: what an expansion leaves behind is exactly the shape
376    // they are for — a clear that frees nothing, and a clear a `return` was
377    // about to make pointless — and running them first would mean running
378    // them twice. See `inline`.
379    inline::expand_small_leaf_calls(&mut program);
380
381    // A clear the `return` after it was going to make pointless is dropped
382    // here rather than never emitted, because the emission sites are many and
383    // the condition is about the *code* — what follows an instruction — which
384    // only the finished code can be asked. See `tails`.
385    tails::drop_clears_before_return(&mut program);
386
387    // And a clear that frees nothing at all — because the word it zeroes is
388    // already null, or is the address of a literal placed once for the
389    // whole run and never collected, whatever this frame does. Here for the
390    // reason above and for one more: the condition is about a *path*
391    // through the finished code, which is a graph the lowering does not
392    // have while it is building one. See `frees`.
393    frees::drop_clears_that_free_nothing(&mut program);
394
395    // A frame wider than a sixteen-bit slot operand can name is the one thing
396    // this lowering refuses about a program it otherwise understood. It is
397    // checked here rather than as each body finishes because here is where
398    // every function exists — a lambda and an instantiation are appended
399    // while another body is still being lowered — and because a diagnostic
400    // about the *program* should list every function at fault rather than the
401    // first. See `limits`.
402    let oversized = limits::oversized_frames(&program);
403    if !oversized.is_empty() {
404        return Err(oversized);
405    }
406
407    // A fault here is a bug in this module, not a fault in the user's
408    // program: everything the verifier checks is something this lowering
409    // decided. Reporting it as a diagnostic would put it in front of the
410    // person least able to act on it, so it fails loudly and with the whole
411    // list, because one lowering bug usually shows up in several places and
412    // seeing all of them is what says which one is the cause.
413    if let Err(faults) = crate::verify(&program) {
414        let listing: Vec<String> = faults.iter().map(ToString::to_string).collect();
415        panic!(
416            "the lowering produced a program the verifier rejects:\n  {}",
417            listing.join("\n  ")
418        );
419    }
420
421    Ok(program)
422}
423
424/// Keeps the first diagnostic about each place.
425///
426/// One unsettled type is read once per operand it feeds, so the same
427/// expression can be reported several times over. What a reader needs is
428/// the place, once.
429fn only_once(errors: Vec<Diagnostic>) -> Vec<Diagnostic> {
430    let mut seen = HashSet::new();
431    errors
432        .into_iter()
433        .filter(|item| {
434            let at = item.primary.map(|span| (span.file.0, span.start, span.end));
435            seen.insert((item.code.clone(), at))
436        })
437        .collect()
438}
439
440// ---------------------------------------------------------------- the plan
441
442/// What one declaration becomes: its identity, and the frame boundary a call
443/// to it has to match.
444struct Decl<'a> {
445    module: Arc<str>,
446    name: Arc<str>,
447    decl: &'a FnDecl,
448    /// `None` for a declaration outside this lowering's scope, and for one
449    /// this pass never asked about. A gap has already been reported for the
450    /// first, so the stub that takes its place is never seen: `lower`
451    /// answers `Err` before the program leaves. The second is a declaration
452    /// the slice left out, and [`Plan::reached`] is what tells the two
453    /// apart.
454    boundary: Option<Boundary>,
455    /// The trait whose default body this method is, when it is one.
456    ///
457    /// What it decides is which substitution the body is lowered under. The
458    /// checker walks a default body **once**, with `self` typed as a rigid
459    /// `Ty::Param("Self")` bounded by the trait, so every fact recorded
460    /// inside it is written in terms of `Self` — which is the same situation
461    /// a generic declaration is in, one parameter at a time. See
462    /// [`Decl::substitution`].
463    from_trait_default: Option<String>,
464    /// The type this is a method of, as the receiver's own type.
465    ///
466    /// `None` for a free function, and for a method of a *generic* type,
467    /// whose receiver's width depends on a type argument this does not have —
468    /// see [`Decl::on_generic_type`].
469    ///
470    /// It is written in the package's own vocabulary — `m.Booking` rather
471    /// than `Booking` — because a conformance may be declared in the module
472    /// that declares the *trait* (ADR 0006's orphan rule), and then the
473    /// type's bare name means nothing where the body is lowered.
474    receiver_ty: Option<Ty>,
475    /// The generic type this is a method of, when it is one.
476    ///
477    /// A method of `Cell<T>` has no boundary of its own for the same reason a
478    /// generic function has none — its receiver's width depends on `T` — and
479    /// it needs one thing more than a generic function does: the parameters
480    /// are the *type*'s rather than the declaration's, so which arguments a
481    /// call settles is read off the receiver rather than off the signature.
482    /// That is not built, and this is what names it as the work rather than
483    /// letting it fail as "a value of type `Cell<T>`", which says where the
484    /// trouble is and not what is owed.
485    on_generic_type: Option<String>,
486}
487
488/// The one type parameter a trait's default body is written in terms of.
489const SELF: &str = "Self";
490
491impl Decl<'_> {
492    /// The type parameters this declaration's facts are recorded in terms
493    /// of, and what this lowering puts in their place.
494    ///
495    /// Empty for almost everything, and then the substitution is the
496    /// identity. A **trait method's default body** is the one declaration
497    /// that is neither generic nor ordinary: `resolve::conform` synthesises
498    /// one `FnDecl` per conforming type, all of them carrying the *trait
499    /// method's* span, and `Checker::check_trait_defaults` records one
500    /// `Signature` at that span with the receiver typed `Ty::Param("Self")`.
501    ///
502    /// So a default body is a generic declaration with one parameter, and
503    /// this is what says which. Nothing else is needed: the boundary is
504    /// [`boundary_of`] under this substitution, the body is [`lower_body`]
505    /// under it, and a call the body makes on `self` finds the conforming
506    /// type's own implementation through [`Body::conformance`] — which is
507    /// the path a bounded generic already takes, for the same reason. One
508    /// recorded walk serves every conformance.
509    ///
510    /// A default body on a *generic* type would need `Self` to stand for an
511    /// instantiation rather than for a declaration, so it is left to
512    /// [`Plan::boundaries`]'s earlier arm.
513    fn substitution(&self) -> (Vec<Arc<str>>, Vec<Ty>) {
514        match (&self.from_trait_default, &self.receiver_ty) {
515            (Some(_), Some(ty)) => (vec![Arc::from(SELF)], vec![ty.clone()]),
516            _ => (Vec::new(), Vec::new()),
517        }
518    }
519}
520
521/// A declaration's parameters and answer, as layouts.
522///
523/// A generic declaration has one of these per instantiation rather than one
524/// of its own, so it is cloned into [`Instance`] and read from there at a
525/// call site — see [`Body::shape`].
526#[derive(Clone)]
527struct Boundary {
528    /// The layout of each parameter, **receiver first** where the
529    /// declaration has one. There are no type groups and nothing is
530    /// permuted; a method's receiver is first because it is the first thing
531    /// a call supplies. A `var` parameter's layout is
532    /// [`shapes::ADDR`]: it names the caller's storage rather than holding a
533    /// value.
534    params: Vec<LayoutId>,
535    /// The types those locations hold, in the same order.
536    ///
537    /// The layout alone is not enough at a call site. A parameter written
538    /// `dyn Trait` and one written `String` are both one [`Repr::Ref`] word,
539    /// and only the first is a place where a concrete value is erased — so
540    /// the call site has to read the type the checker settled, not the
541    /// layout this lowering derived from it.
542    types: Vec<Ty>,
543    returns: LayoutId,
544    /// What the declaration answers, as the checker settled it.
545    ///
546    /// The layout is not enough for `?`, which has to build the enclosing
547    /// function's own `Err` or `None` and therefore needs to know which of
548    /// the two the answer is.
549    ret: Ty,
550    /// Whether the first parameter is the receiver: `self`, or the address
551    /// `var self` names.
552    receiver: bool,
553    /// Whether the last parameter collects the arguments the ones before it
554    /// did not take.
555    ///
556    /// One flag rather than a position, because the checker has already
557    /// refused a variadic parameter anywhere but last — `cove::type::
558    /// variadic_position` — and refused one written with a default.
559    variadic: bool,
560    /// Whether the declaration was written `async fn`.
561    ///
562    /// It changes nothing about the function and everything about the call.
563    /// `returns` above is the layout of `T` and not of `Task<T>`, because
564    /// the checker's `Signature::ret` is `T` and because the oracle's
565    /// `Interpreter::invoke_body` produces a `T` — the task is made *around*
566    /// the answer, by the caller, after the body has already run. So the
567    /// declaration is lowered as an ordinary function and every Cove call
568    /// site follows its [`Inst::Call`] with an [`Inst::Settled`].
569    ///
570    /// The three places that reach a body from outside Cove — an entry, a
571    /// host `invoke`, and a host calling a Cove callback — all *await* what
572    /// they get in the oracle, and awaiting a settled task is the value.
573    /// Here they get the value, because no task was made. That is the same
574    /// answer arrived at by not building the thing that would be undone.
575    is_async: bool,
576}
577
578/// Every declaration the package will have a [`Function`] for, numbered.
579///
580/// The order is module then name, both from a `BTreeMap`, so a package
581/// lowers to the same function ids every time it is lowered. A test that
582/// pins a listing is pinning something stable rather than a hash order.
583/// Within a module the free functions come first and the methods follow, so
584/// adding a method to a type does not renumber a package's functions.
585struct Plan<'a> {
586    decls: Vec<Decl<'a>>,
587    by_name: BTreeMap<(Arc<str>, Arc<str>), FunctionId>,
588    lookup: HashMap<(String, String), FunctionId>,
589    /// A method, keyed the way [`MethodTarget`] names one: the module that
590    /// declares the *type*, the type, and the method.
591    ///
592    /// That is not always the module the `impl` block is written in — ADR
593    /// 0006's orphan rule lets a conformance be written where the trait is —
594    /// so this is keyed by what a call site holds rather than by where the
595    /// code ended up.
596    methods: HashMap<(String, String, String), FunctionId>,
597    /// The declarations this pass is lowering rather than stubbing.
598    ///
599    /// It is the whole numbering for [`lower`] and one entry's reachable set
600    /// for [`lower_entry`]. [`Plan::reached`] is what reads it, and every
601    /// place that names a declaration asks before it emits a call.
602    lowered: HashSet<FunctionId>,
603}
604
605impl<'a> Plan<'a> {
606    /// Numbers every declaration the package has.
607    ///
608    /// The numbering is over the whole package whether or not a slice will
609    /// use all of it, and that is what makes a [`FunctionId`] mean the same
610    /// thing in every pass [`lower_entry`] runs: a set of ids gathered by one
611    /// round names the same declarations in the next.
612    ///
613    /// Nothing here reads a signature or builds a layout. What a call to a
614    /// declaration passes is [`Plan::boundaries`], which is asked only about
615    /// the declarations a pass is actually lowering — so a slice pays for the
616    /// types it reaches and not for the package's.
617    fn index(checked: &'a Checked) -> Plan<'a> {
618        let mut plan = Plan {
619            decls: Vec::new(),
620            by_name: BTreeMap::new(),
621            lookup: HashMap::new(),
622            methods: HashMap::new(),
623            lowered: HashSet::new(),
624        };
625        for (name, resolved) in &checked.modules {
626            for (fn_name, entry) in &resolved.functions {
627                let module: Arc<str> = Arc::from(name.as_str());
628                let id = plan.declare(module, Arc::from(fn_name.as_str()), entry.decl.as_ref());
629                plan.lookup.insert((name.clone(), fn_name.clone()), id);
630            }
631            for ((type_name, method), entry) in &resolved.methods {
632                let module: Arc<str> = Arc::from(name.as_str());
633                // A method is named `Type.method` in the module whose `impl`
634                // block writes it. A type and a free function of one name
635                // cannot both be declared in a module, and a `.` is not a
636                // name character, so the two namings cannot collide and
637                // `m.Point.scaled` reads in a diagnostic as it is written.
638                let lowered: Arc<str> = Arc::from(format!("{type_name}.{method}"));
639                let id = plan.declare(module, lowered, entry.decl.as_ref());
640                plan.decls[id.index()].from_trait_default = entry.from_trait_default.clone();
641                let owner = resolved.owner_of(type_name).unwrap_or(name.as_str());
642                if is_generic_type(checked, owner, type_name) {
643                    plan.decls[id.index()].on_generic_type = Some(type_name.clone());
644                } else {
645                    plan.decls[id.index()].receiver_ty = receiver_ty(checked, owner, type_name);
646                }
647                plan.methods
648                    .insert((owner.to_string(), type_name.clone(), method.clone()), id);
649            }
650        }
651        plan
652    }
653
654    /// Reads the boundary of every declaration in `reach`, and reports what
655    /// stopped one.
656    ///
657    /// This is where a pass's errors about *declarations* come from, and
658    /// restricting it to the slice is most of what slicing is worth: a
659    /// generic function or an `async fn` in a module the entry never enters
660    /// is not work this entry is waiting on.
661    fn boundaries(
662        &mut self,
663        checked: &'a Checked,
664        reach: &HashSet<FunctionId>,
665        pool: &mut Pool,
666        errors: &mut Vec<Diagnostic>,
667    ) {
668        self.lowered = reach.clone();
669        for at in 0..self.decls.len() {
670            let id = FunctionId(at as u32);
671            if !reach.contains(&id) {
672                continue;
673            }
674            let decl = &self.decls[at];
675            let module = decl.module.to_string();
676            let (generics, args) = decl.substitution();
677            let boundary = if let Some(type_name) = &decl.on_generic_type {
678                let named = format!("`{type_name}.{}`", short_name(&decl.name));
679                errors.push(gap::gap(
680                    &format!("{named}, a method of a generic type"),
681                    decl.decl.span,
682                ));
683                None
684            } else if decl.from_trait_default.is_some() && generics.is_empty() {
685                // A default body whose conforming type this lowering could
686                // not name. Nothing in the corpus reaches it — a conformance
687                // is declared for a type of the package — and it is named
688                // rather than left out because the alternative is a stub that
689                // answers `()`.
690                let named = format!("`{}`", decl.name);
691                errors.push(gap::gap(
692                    &format!("{named}, a trait method's default body on a type with no layout"),
693                    decl.decl.span,
694                ));
695                None
696            } else if !decl.decl.generics.is_empty() {
697                // A generic declaration has no one boundary. Its parameters'
698                // widths depend on what its type parameters stand for —
699                // `Cell<Int>` is one word and `Cell<Point>` is two — so the
700                // boundary belongs to an instantiation and
701                // [`Body::instantiate`] reads one per set of arguments. What
702                // stands here is a stub nothing names.
703                None
704            } else {
705                boundary_of(checked, &module, decl.decl, &generics, &args, pool, errors)
706            };
707            self.decls[at].boundary = boundary;
708        }
709    }
710
711    /// Numbers one declaration and records the name it answers to.
712    fn declare(&mut self, module: Arc<str>, name: Arc<str>, decl: &'a FnDecl) -> FunctionId {
713        let id = FunctionId(self.decls.len() as u32);
714        self.by_name.insert((module.clone(), name.clone()), id);
715        self.decls.push(Decl {
716            module,
717            name,
718            decl,
719            boundary: None,
720            from_trait_default: None,
721            receiver_ty: None,
722            on_generic_type: None,
723        });
724        id
725    }
726
727    /// The declarations any of `roots` can reach, as the checker's call
728    /// graph answers it.
729    ///
730    /// A seed rather than a verdict: see [`lower_roots`] for what the graph
731    /// cannot see and what closes the gap.
732    ///
733    /// One walk over every root rather than one walk each, because the
734    /// answer is a union and `seen` is what makes a shared callee cost the
735    /// walk once no matter how many roots reach it.
736    ///
737    /// This does *not* seed the walk with
738    /// [`cove_schema::builtins::standard_library`]'s functions, and that
739    /// was tried and measured wrong rather than assumed: seeding
740    /// `std.array.isEmpty` put it in `reach` whether or not any root called
741    /// it, and a generic declaration's *un-instantiated* id in `reach` is
742    /// not nothing — [`Plan::boundaries`] gives it no [`Boundary`] and
743    /// [`lower_function`] stubs it, so every lowered program carried a
744    /// dead, nameless stub function for a method it never called. A call
745    /// that *does* reach `std.array.isEmpty` is still found, one round
746    /// later, by the same `wanted` correction documented on
747    /// [`lower_roots`] that finds any other declaration `reach` left out —
748    /// [`Body::call_target`]'s `reached` check defers the call site to the
749    /// next round exactly as it would for a package's own generic function,
750    /// and a probe confirmed the two are lowered identically. So a builtin
751    /// method whose body has moved into the standard library costs a
752    /// program nothing extra unless a program actually calls it, which is
753    /// the same promise every other builtin already keeps.
754    fn reachable_from(&self, checked: &'a Checked, roots: &[(&str, &str)]) -> HashSet<FunctionId> {
755        let mut seen: BTreeSet<Node> = BTreeSet::new();
756        let mut stack: Vec<Node> = roots
757            .iter()
758            .map(|(module, name)| (module.to_string(), FnKey::Fn(name.to_string())))
759            .collect();
760        while let Some(node) = stack.pop() {
761            if !seen.insert(node.clone()) {
762                continue;
763            }
764            let Some(edges) = checked.call_graph.get(&node) else {
765                continue;
766            };
767            stack.extend(edges.keys().cloned());
768        }
769        seen.iter().filter_map(|node| self.id_of(node)).collect()
770    }
771
772    /// The declaration a call-graph node names.
773    fn id_of(&self, node: &Node) -> Option<FunctionId> {
774        let (module, key) = node;
775        match key {
776            FnKey::Fn(name) => self.lookup.get(&(module.clone(), name.clone())).copied(),
777            FnKey::Method(type_name, method) => self
778                .by_name
779                .get(&(
780                    Arc::from(module.as_str()),
781                    Arc::from(format!("{type_name}.{method}")),
782                ))
783                .copied(),
784        }
785    }
786
787    /// Whether this pass lowered `id` rather than stubbing it.
788    ///
789    /// Every place that turns a name into a [`FunctionId`] asks this before
790    /// it emits anything naming one, because a stub answers `()` and a call
791    /// to it would be a wrong answer rather than a refusal. What a caller
792    /// does with a `false` is [`Body::reached`]: record the declaration and
793    /// let the next pass lower it.
794    fn reached(&self, id: FunctionId) -> bool {
795        self.lowered.contains(&id)
796    }
797
798    /// The declaration `name` denotes where the module `from` can see it.
799    ///
800    /// A module's own declaration wins over an imported one, which is the
801    /// order resolution already established: a `use` that would shadow a
802    /// local declaration was refused there.
803    fn resolve(&self, checked: &Checked, from: &str, name: &str) -> Option<FunctionId> {
804        if let Some(id) = self.lookup.get(&(from.to_string(), name.to_string())) {
805            return Some(*id);
806        }
807        let owner = checked.modules.get(from)?.imports.get(name)?;
808        self.lookup.get(&(owner.clone(), name.to_string())).copied()
809    }
810
811    /// The function a [`MethodTarget`] names.
812    fn method(&self, target: &MethodTarget) -> Option<FunctionId> {
813        self.methods
814            .get(&(
815                target.module.clone(),
816                target.type_name.clone(),
817                target.method.clone(),
818            ))
819            .copied()
820    }
821
822    /// The function `type_module.type_name` answers `method` with.
823    fn method_of(&self, type_module: &str, type_name: &str, method: &str) -> Option<FunctionId> {
824        self.methods
825            .get(&(
826                type_module.to_string(),
827                type_name.to_string(),
828                method.to_string(),
829            ))
830            .copied()
831    }
832
833    /// What a call to `id` passes and answers, as owned values: a call site
834    /// reads this while it is still holding the body it is lowering.
835    ///
836    /// `None` for an id past the declarations — a lambda or an instantiation
837    /// — which [`Body::shape`] answers instead.
838    fn shape(&self, id: FunctionId) -> Option<CallShape> {
839        Some(self.decls.get(id.index())?.boundary.as_ref()?.shape())
840    }
841}
842
843impl Boundary {
844    /// What one call site has to match, as owned values.
845    fn shape(&self) -> CallShape {
846        CallShape {
847            params: self.params.clone(),
848            types: self.types.clone(),
849            returns: self.returns,
850            receiver: self.receiver,
851            variadic: self.variadic,
852            is_async: self.is_async,
853        }
854    }
855}
856
857/// What one call site has to match, held apart from the [`Plan`] so that a
858/// body can read it while it is writing into its own frame.
859struct CallShape {
860    params: Vec<LayoutId>,
861    types: Vec<Ty>,
862    returns: LayoutId,
863    receiver: bool,
864    variadic: bool,
865    is_async: bool,
866}
867
868impl CallShape {
869    /// How many parameters the call site writes, which is every one but the
870    /// receiver.
871    ///
872    /// It is no longer the number of *arguments* a call passes: a variadic
873    /// parameter takes any number and a defaulted one takes none, so what
874    /// lines a call up with a frame is [`Body::assign`] rather than a count.
875    fn written(&self) -> usize {
876        self.params.len() - usize::from(self.receiver)
877    }
878
879    /// The layout of written parameter `at`, past the receiver.
880    fn param(&self, at: usize) -> LayoutId {
881        self.params[usize::from(self.receiver) + at]
882    }
883
884    /// The type of written parameter `at`, past the receiver.
885    ///
886    /// For a variadic one this is the *element* type, because that is what
887    /// each collected argument is.
888    fn ty(&self, at: usize) -> &Ty {
889        &self.types[usize::from(self.receiver) + at]
890    }
891}
892
893/// The type a method of `owner`'s declaration of `name` receives, written
894/// the way the package names it.
895///
896/// `m.Booking` rather than `Booking`, because a conformance may be written
897/// in the module that declares the *trait* — ADR 0006's orphan rule — and
898/// the type's bare name means nothing there. It is the same reason
899/// [`shapes::qualified`] exists, and `shapes::declaring` reads a qualified
900/// name back apart.
901///
902/// A method's receiver is otherwise read off the checker's `Signature`, and
903/// this is not a second answer to that: it is asked only where a signature
904/// records `Ty::Param("Self")` and something has to say what `Self` is.
905///
906/// A declaration this cannot place — a conformance on a type the package
907/// does not declare — answers `None`, and a default body on one is a gap.
908fn receiver_ty(checked: &Checked, owner: &str, name: &str) -> Option<Ty> {
909    let resolved = checked.modules.get(owner)?;
910    let qualified: Arc<str> = Arc::from(format!("{owner}.{name}"));
911    if resolved.structs.contains_key(name) {
912        return Some(Ty::Struct(qualified, Vec::new()));
913    }
914    if resolved.enums.contains_key(name) {
915        return Some(Ty::Enum(qualified, Vec::new()));
916    }
917    None
918}
919
920/// Whether `owner`'s declaration of `name` binds type parameters.
921fn is_generic_type(checked: &Checked, owner: &str, name: &str) -> bool {
922    let Some(resolved) = checked.modules.get(owner) else {
923        return false;
924    };
925    let generic = |generics: &[cove_syntax::ast::GenericParam]| !generics.is_empty();
926    resolved
927        .structs
928        .get(name)
929        .is_some_and(|entry| generic(&entry.decl.generics))
930        || resolved
931            .enums
932            .get(name)
933            .is_some_and(|entry| generic(&entry.decl.generics))
934}
935
936/// The method half of a `Type.method` declaration name.
937fn short_name(name: &str) -> &str {
938    name.rsplit_once('.').map_or(name, |(_, method)| method)
939}
940
941/// What a call to this declaration passes and answers, read off the
942/// checker's signature rather than off the source annotations.
943///
944/// The annotations are names; the signature is what those names resolved to
945/// in the module they were written in, which is the only reading of a
946/// `-> other.Thing` that means the same in both modules.
947///
948/// `generics` and `args` are the declaration's type parameters and what this
949/// instantiation puts in their place, and they are empty for a declaration
950/// that binds none. A generic declaration has a boundary *per instantiation*
951/// and no boundary of its own: `fn f<T>(x: T)` says how many parameters there
952/// are and nothing about how wide one is, and a width is what a frame is made
953/// of.
954#[allow(clippy::too_many_arguments)]
955fn boundary_of(
956    checked: &Checked,
957    module: &str,
958    decl: &FnDecl,
959    generics: &[Arc<str>],
960    args: &[Ty],
961    pool: &mut Pool,
962    errors: &mut Vec<Diagnostic>,
963) -> Option<Boundary> {
964    let mut ok = true;
965    let Some(signature) = checked.facts.signature(decl.span.file, decl.span) else {
966        errors.push(gap::gap(
967            "a declaration the checker recorded no signature for",
968            decl.span,
969        ));
970        return None;
971    };
972
973    let mut params = Vec::new();
974    let mut types = Vec::new();
975    // The receiver comes first because that is the order a call supplies it
976    // in, and `Signature` records it apart from the parameters so that this
977    // does not have to be inferred from a count.
978    if let Some(receiver) = &signature.receiver {
979        let span = decl.receiver.map_or(decl.span, |it| it.span);
980        let receiver = &receiver.instantiate(generics, args);
981        match pool.shapes.of(checked, module, receiver) {
982            // `var self` is a `var` parameter written in the receiver
983            // position: the method names the caller's storage, so the first
984            // parameter holds its address and a write to a field of `self`
985            // reaches the caller's own words with no copy back.
986            Some(_) if decl.receiver.is_some_and(|it| it.is_var) => params.push(shapes::ADDR),
987            Some(layout) => params.push(layout),
988            None => {
989                errors.push(describe(&pool.shapes, receiver, span));
990                ok = false;
991            }
992        }
993        types.push(receiver.clone());
994    }
995    for (param, ty) in decl.params.iter().zip(&signature.params) {
996        let ty = &ty.instantiate(generics, args);
997        // A variadic parameter is an immutable `Array<T>` inside the body
998        // whatever stands in front of it, and the signature records the
999        // element type `T` rather than the array — so the location the callee
1000        // reads is one layout wider out than the one a written argument fits
1001        // into. `Boundary::types` keeps the element type, because that is
1002        // what each collected argument is erased to.
1003        let held = if param.variadic {
1004            Ty::Array(Box::new(ty.clone()))
1005        } else {
1006            ty.clone()
1007        };
1008        match pool.shapes.of(checked, module, &held) {
1009            // A `var` parameter is an ordinary slot whose `Repr` is `Addr`:
1010            // it names the caller's storage, so the word is the address of
1011            // it rather than a copy of what is in it. The type is still
1012            // read, because a type with no layout is a gap whichever side of
1013            // the alias it is on. A variadic one is not an alias whatever the
1014            // source wrote, which is the `is_var && !variadic` the checker's
1015            // own `ParamSig` records.
1016            Some(_) if param.is_var && !param.variadic => params.push(shapes::ADDR),
1017            Some(layout) => params.push(layout),
1018            None => {
1019                errors.push(describe(&pool.shapes, &held, param.span));
1020                ok = false;
1021            }
1022        }
1023        types.push(ty.clone());
1024    }
1025    let ret = signature.ret.instantiate(generics, args);
1026    let returns = match pool.shapes.of(checked, module, &ret) {
1027        Some(layout) => layout,
1028        None => {
1029            let span = decl.return_type.as_ref().map_or(decl.span, |ty| ty.span);
1030            errors.push(describe(&pool.shapes, &ret, span));
1031            ok = false;
1032            shapes::UNIT
1033        }
1034    };
1035
1036    ok.then_some(Boundary {
1037        receiver: signature.receiver.is_some(),
1038        variadic: decl.params.last().is_some_and(|param| param.variadic),
1039        // The signature's `ret` is `T` for an `async fn`, so `returns` above
1040        // is the layout of the value the body produces and the handle is the
1041        // call site's to make. See `Boundary::is_async`.
1042        is_async: decl.is_async,
1043        params,
1044        types,
1045        returns,
1046        ret,
1047    })
1048}
1049
1050/// Why a type has no layout here: the checker settled nothing, it settled a
1051/// declaration whose layout contains itself, or it settled something this
1052/// task has not reached.
1053///
1054/// The middle one is separated because it is not the same kind of thing.
1055/// [ADR 0035](../../../../docs/adr/0035-a-value-type-may-not-contain-itself.md)
1056/// makes an implicitly recursive value layout a *checker* error, so this is a
1057/// program that will stop being a program — and saying only "a value of type
1058/// `Node`" would read as a piece of work someone here still owes.
1059fn describe(shapes: &Shapes, ty: &Ty, span: Span) -> Diagnostic {
1060    match ty {
1061        Ty::Unknown(_) => gap::unknown(ty, span),
1062        Ty::Struct(name, _) | Ty::Enum(name, _) if shapes.contains_itself(name) => {
1063            gap::gap(&format!("`{name}`, whose layout contains itself"), span)
1064        }
1065        _ => gap::gap(&format!("a value of type `{ty}`"), span),
1066    }
1067}
1068
1069// ------------------------------------------------------------ interning
1070
1071/// The program-wide pool of argument lists.
1072///
1073/// A call's arguments are a static list of source slots, and a repeated call
1074/// shape is one list rather than one per site — which is the whole reason
1075/// [`Inst::Call`] names an [`ArgsId`] instead of carrying the list inline.
1076#[derive(Default)]
1077struct Args {
1078    lists: Vec<Vec<Arg>>,
1079    index: HashMap<Vec<Arg>, ArgsId>,
1080}
1081
1082impl Args {
1083    fn intern(&mut self, args: Vec<Arg>) -> ArgsId {
1084        if let Some(id) = self.index.get(&args) {
1085            return *id;
1086        }
1087        let id = ArgsId(self.lists.len() as u32);
1088        self.index.insert(args.clone(), id);
1089        self.lists.push(args);
1090        id
1091    }
1092}
1093
1094/// Everything a [`Program`] holds once for the whole package, being built.
1095///
1096/// It is one struct rather than a parameter each because every one of them
1097/// is written from inside a body and read only when the program is
1098/// assembled: a body that meets a string literal, a `match`, a host call or
1099/// a struct is adding to a table that outlives the function it is in.
1100///
1101/// Each table interns. Two call sites of the same shape share one argument
1102/// list, two `"{n}"`s share one string, and two `Option<Int>`s share one
1103/// layout — which is what keeps these tables as long as the shapes a program
1104/// has rather than as long as the expressions that mention them.
1105struct Pool {
1106    args: Args,
1107    strings: Vec<Arc<str>>,
1108    tables: Vec<Table>,
1109    host_ops: Vec<HostOp>,
1110    builtins: Vec<Builtin>,
1111    shapes: Shapes,
1112    /// The functions numbered after every declaration: the body a lambda
1113    /// lowered to, and the body one instantiation of a generic declaration
1114    /// lowered to.
1115    ///
1116    /// A slot is reserved — `None` — before the body is lowered, because
1117    /// that body may close over a lambda or ask for an instantiation of its
1118    /// own and the inner one has to be numbered after the outer. So the
1119    /// entry is filled in on the way back out, and a `None` left at the end
1120    /// would be a lowering that reserved a number and never used it.
1121    ///
1122    /// The two kinds share one list because they share the one thing that
1123    /// matters about it — a number past the declarations, taken before the
1124    /// body is known — and two lists would have to agree on which of them a
1125    /// given number was from.
1126    appended: Vec<Option<Function>>,
1127    /// What each instantiation is, keyed by the id it was given.
1128    ///
1129    /// A call site reads a boundary and a declaration off this the way it
1130    /// reads them off [`Plan`] for an ordinary declaration.
1131    instances: HashMap<FunctionId, Instance>,
1132    /// The id one declaration at one set of type arguments was given.
1133    ///
1134    /// This is what makes a generic instantiated twice at one type cost one
1135    /// function, and it is also what makes a *recursive* generic terminate:
1136    /// the id is recorded before the body is lowered, so a call the body
1137    /// makes to itself finds the number rather than starting again.
1138    instance_ids: HashMap<(FunctionId, String), FunctionId>,
1139    /// The instantiations being lowered right now, outermost first.
1140    ///
1141    /// A chain rather than a count, because what a program that exceeds the
1142    /// bound needs told is which instantiation asked for which — see
1143    /// [`Body::instantiate`].
1144    open: Vec<String>,
1145}
1146
1147/// One monomorphisation: which declaration it lowers, and for what.
1148///
1149/// A generic declaration is not a function here. `fn f<T>(x: T)` says how
1150/// many parameters there are and nothing about how wide one is, and a width
1151/// is what a frame is made of — so what is lowered is one `Function` per set
1152/// of type arguments, and this is what says which one.
1153struct Instance {
1154    /// The generic declaration in [`Plan::decls`], which is where the labels,
1155    /// the defaults and the syntax of the body are read from.
1156    decl: FunctionId,
1157    /// The type parameters the declaration binds, in declaration order.
1158    generics: Vec<Arc<str>>,
1159    /// What this instantiation puts in their place, in the same order.
1160    args: Vec<Ty>,
1161    /// The boundary those arguments settle.
1162    boundary: Boundary,
1163}
1164
1165impl Pool {
1166    fn new(schemas: HostSchemas) -> Pool {
1167        Pool {
1168            args: Args::default(),
1169            strings: Vec::new(),
1170            tables: Vec::new(),
1171            host_ops: Vec::new(),
1172            builtins: Vec::new(),
1173            shapes: Shapes::new(schemas),
1174            appended: Vec::new(),
1175            instances: HashMap::new(),
1176            instance_ids: HashMap::new(),
1177            open: Vec::new(),
1178        }
1179    }
1180
1181    fn string(&mut self, text: &str) -> StrId {
1182        match self.strings.iter().position(|held| &**held == text) {
1183            Some(at) => StrId(at as u32),
1184            None => {
1185                self.strings.push(Arc::from(text));
1186                StrId((self.strings.len() - 1) as u32)
1187            }
1188        }
1189    }
1190
1191    /// A jump table. Not interned: a `match`'s targets are program counters
1192    /// of the function it is in, so two tables that happen to agree agree by
1193    /// accident.
1194    fn table(&mut self, table: Table) -> TableId {
1195        self.tables.push(table);
1196        TableId((self.tables.len() - 1) as u32)
1197    }
1198
1199    fn host_op(&mut self, op: HostOp) -> HostOpId {
1200        match self.host_ops.iter().position(|held| *held == op) {
1201            Some(at) => HostOpId(at as u32),
1202            None => {
1203                self.host_ops.push(op);
1204                HostOpId((self.host_ops.len() - 1) as u32)
1205            }
1206        }
1207    }
1208
1209    fn builtin(&mut self, builtin: Builtin) -> BuiltinId {
1210        match self.builtins.iter().position(|held| *held == builtin) {
1211            Some(at) => BuiltinId(at as u32),
1212            None => {
1213                self.builtins.push(builtin);
1214                BuiltinId((self.builtins.len() - 1) as u32)
1215            }
1216        }
1217    }
1218}
1219
1220// --------------------------------------------------------------- one body
1221
1222/// A loop being lowered, and what it owes its `break`s.
1223struct Loop {
1224    /// Where `continue` goes: the condition, so the next turn is decided
1225    /// again rather than assumed.
1226    head: Pc,
1227    /// How many scopes were open outside the body, so an early exit knows
1228    /// which ones it is leaving.
1229    depth: usize,
1230    /// How many temporaries were live outside the loop, so an early exit
1231    /// knows which ones it made and which ones it merely found.
1232    ///
1233    /// A `break` clears the temporaries above this mark and none below it.
1234    /// The ones below are the loop's own machinery and the enclosing
1235    /// expression's — the array a `for` is walking is read again after the
1236    /// `break` lands, and an enclosing loop's is read for the rest of *its*
1237    /// run.
1238    held: usize,
1239    /// Jumps emitted by `break` with nowhere to go yet.
1240    breaks: Vec<Pc>,
1241    /// The location a `for` binds each turn, when it holds a reference.
1242    ///
1243    /// The loop owns it rather than the per-turn scope, because the scope
1244    /// gives its slots back when it ends and the next turn writes this one
1245    /// again. That leaves nobody to clear it on the one path that does not
1246    /// reach the end of a turn, which is what this is: a `break` clears the
1247    /// element it was holding on its way out.
1248    element: Option<Dest>,
1249}
1250
1251/// A task scope being lowered, and what leaving it early owes it.
1252struct OpenScope {
1253    /// The `Repr::Scope` slot the [`Inst::ScopeEnter`] wrote.
1254    slot: Slot,
1255    /// How many loops were open outside this scope.
1256    ///
1257    /// What it decides is which of the two directions a jump is going. A
1258    /// `break` leaves every scope opened *inside* its own loop and none
1259    /// opened outside it, and that is the same question `Loop::depth` asks
1260    /// about lexical scopes, asked the other way round.
1261    loops: usize,
1262    /// Whether any child spawned into this scope answers a `Result`.
1263    ///
1264    /// What it decides is whether leaving the scope can produce a failure at
1265    /// all. `wait_for_children` returns a child's `Err` from the function the
1266    /// scope was written in, so that function must be able to carry one — but
1267    /// only if a child can *make* one, and a scope over `Task<Verdict>`
1268    /// children cannot. Asking every scope for a failure layout refused two
1269    /// corpus programs the checker had already cleared, for the same reason
1270    /// and by the same predicate `Checker::spawned` uses.
1271    can_fail: bool,
1272}
1273
1274/// The state of lowering one function body.
1275struct Body<'a> {
1276    checked: &'a Checked,
1277    /// The package's own text, which `assert` and `assertEqual` quote.
1278    ///
1279    /// Nothing else in this crate reads it: a lowering answers what the
1280    /// checker settled, and source text is not one of those answers. The two
1281    /// assertions are the exception the language itself makes — their failure
1282    /// message names the condition in the words the test was written in, and
1283    /// only the compiler has them.
1284    sources: &'a SourceMap,
1285    plan: &'a Plan<'a>,
1286    pool: &'a mut Pool,
1287    errors: &'a mut Vec<Diagnostic>,
1288    /// The declarations this body named that the pass had left out of its
1289    /// slice. See [`lower_entry`].
1290    wanted: &'a mut HashSet<FunctionId>,
1291    /// The module the body is written in, which is what an unqualified name
1292    /// in it is resolved against.
1293    module: &'a str,
1294    /// What this body is called, which is what a lambda written inside it is
1295    /// named after: `f#0`, and `f#0#0` for one nested in that.
1296    name: Arc<str>,
1297    /// How many lambdas this body has already made, which is the number the
1298    /// next one is given.
1299    lambdas: u32,
1300    frame: Frame,
1301    code: Vec<Inst>,
1302    spans: Vec<Span>,
1303    loops: Vec<Loop>,
1304    /// The task scopes this body has open, outermost first.
1305    ///
1306    /// A scope is left by waiting for or cancelling its children, and there
1307    /// are two ways out of one: the body reaches its end, which is
1308    /// [`Inst::ScopeLeave`], or control leaves through a `return`, a `?`, a
1309    /// `break` or a `continue`, which is [`Inst::ScopeCancel`]. Only the
1310    /// first is written where the `scope` is. The second is an obligation on
1311    /// every exit path, exactly as [`Inst::Clear`] is, and this is the list
1312    /// that says which scopes a given jump is leaving.
1313    scopes: Vec<OpenScope>,
1314    /// The temporaries this body is holding that a collection would trace,
1315    /// innermost last.
1316    ///
1317    /// A scope answers which *bindings* it owns, and that is what
1318    /// [`Frame::pop_scope`] and [`Frame::refs_within`] are for. A temporary
1319    /// belongs to no scope: it is the expression's own, and the expression
1320    /// that made it ends its live range with [`Body::release`]. That works
1321    /// for every path that reaches the release — and an early exit does not.
1322    ///
1323    /// `f(a, if c { b } else { break })` evaluates `a` into a temporary, and
1324    /// the `break` leaves before the call that would have consumed it. The
1325    /// scopes hold nothing about `a`, so `leave_turn` cleared the bindings
1326    /// and the loop's element and left the temporary holding a reference for
1327    /// the rest of the frame. This is the list that answers it.
1328    held: Vec<(Slot, LayoutId)>,
1329    /// The location the body's answer is assembled in, and the one the
1330    /// trailing [`Inst::Return`] names.
1331    answer: Dest,
1332    /// What this function answers, as a type rather than as a layout.
1333    ///
1334    /// `?` needs it: the value it leaves through is the enclosing
1335    /// function's own `Err` or `None`, built here, and building one needs
1336    /// to know which of the two *this* function answers rather than what the
1337    /// `?` was applied to.
1338    returns: Ty,
1339    /// The type parameters the declaration this body lowers binds, in
1340    /// declaration order. Empty for a declaration that binds none.
1341    generics: Vec<Arc<str>>,
1342    /// What this instantiation puts in their place, in the same order.
1343    ///
1344    /// The checker walked a generic body **once**, with its parameters rigid,
1345    /// so every fact recorded inside it is written in terms of `generics`.
1346    /// This is what completes one: [`Body::ty`] answers `m.Article` where the
1347    /// fact says `T`, and everything downstream — a layout, a width, which
1348    /// conformance a bounded call reaches — falls out of that one
1349    /// substitution rather than out of a rule per construct.
1350    args: Vec<Ty>,
1351    /// The layout of the value behind each [`shapes::ADDR`] slot: what a
1352    /// `var` parameter, or a `var self`, names in the caller's frame.
1353    ///
1354    /// A slot's [`Repr`] is all a frame records, and `Addr` says only that
1355    /// the word is an address. Almost nothing needs more, because every
1356    /// *read* of a `var` parameter is at the layout the checker settled for
1357    /// the expression doing the reading — [`Body::name`] and
1358    /// [`Body::place_of`] both take it from there.
1359    ///
1360    /// A capture is the one place with no such expression: `Body::captured_by`
1361    /// holds a name and a slot and nothing the checker recorded a type for.
1362    /// So the parameter's own layout is written down where the boundary was
1363    /// read, which is the only place it is known without asking a second
1364    /// time.
1365    aliases: HashMap<Slot, LayoutId>,
1366}
1367
1368#[allow(clippy::too_many_arguments)]
1369fn lower_function(
1370    checked: &Checked,
1371    sources: &SourceMap,
1372    plan: &Plan,
1373    id: usize,
1374    pool: &mut Pool,
1375    errors: &mut Vec<Diagnostic>,
1376    wanted: &mut HashSet<FunctionId>,
1377) -> Function {
1378    let decl = &plan.decls[id];
1379    let Some(boundary) = &decl.boundary else {
1380        return stub(decl);
1381    };
1382    let name = decl.name.clone();
1383    // The same substitution the boundary was read under, so that a fact
1384    // recorded in terms of `Self` completes to the same type in the frame
1385    // and in the body.
1386    let (generics, args) = decl.substitution();
1387    lower_body(
1388        checked, sources, plan, decl, boundary, name, &generics, &args, pool, errors, wanted,
1389    )
1390}
1391
1392/// Lowers one declaration's body, at one instantiation of its type
1393/// parameters.
1394///
1395/// `generics` and `args` are empty for an ordinary declaration, and then the
1396/// substitution is the identity and this is exactly what it always was. For a
1397/// generic declaration they are what the call site asked for, and they are
1398/// carried on the [`Body`] rather than applied to the syntax: the checker
1399/// walked the body once, so the facts are recorded once in terms of the
1400/// parameters, and completing a fact as it is read is what makes one recorded
1401/// walk serve every instantiation.
1402#[allow(clippy::too_many_arguments)]
1403fn lower_body(
1404    checked: &Checked,
1405    sources: &SourceMap,
1406    plan: &Plan,
1407    decl: &Decl,
1408    boundary: &Boundary,
1409    name: Arc<str>,
1410    generics: &[Arc<str>],
1411    args: &[Ty],
1412    pool: &mut Pool,
1413    errors: &mut Vec<Diagnostic>,
1414    wanted: &mut HashSet<FunctionId>,
1415) -> Function {
1416    let mut frame = Frame::new();
1417    let mut param_slots = Vec::with_capacity(boundary.params.len());
1418    for layout in &boundary.params {
1419        param_slots.push(frame.param(pool.shapes.words(*layout)));
1420    }
1421    // What each `var` parameter names, at the width the parameter was
1422    // declared. `boundary_of` resolved that type to a layout before it chose
1423    // `ADDR` for the slot, so this asks the interned table for an answer it
1424    // already holds.
1425    let mut aliases = HashMap::new();
1426    for (at, layout) in boundary.params.iter().enumerate() {
1427        if *layout != shapes::ADDR {
1428            continue;
1429        }
1430        if let Some(held) = pool.shapes.of(checked, &decl.module, &boundary.types[at]) {
1431            aliases.insert(param_slots[at], held);
1432        }
1433    }
1434    // The answer is taken before any temporary, so it is live for the whole
1435    // body and never handed to something else.
1436    let answer = Dest {
1437        slot: frame.alloc(pool.shapes.words(boundary.returns)),
1438        layout: boundary.returns,
1439    };
1440
1441    let mut body = Body {
1442        checked,
1443        sources,
1444        plan,
1445        pool,
1446        errors,
1447        wanted,
1448        module: &decl.module,
1449        name: name.clone(),
1450        lambdas: 0,
1451        frame,
1452        code: Vec::new(),
1453        spans: Vec::new(),
1454        loops: Vec::new(),
1455        scopes: Vec::new(),
1456        held: Vec::new(),
1457        answer,
1458        returns: boundary.ret.clone(),
1459        generics: generics.to_vec(),
1460        args: args.to_vec(),
1461        aliases,
1462    };
1463
1464    body.frame.push_scope();
1465    // The receiver is the first parameter where there is one, so a written
1466    // parameter's location is its position shifted past it. Nothing else
1467    // about a method differs: the body reads `self` the way it reads any
1468    // binding, and where the receiver is an `Addr` — `var self` — reading it
1469    // is a `Load` through the word, which is the same rule a `var` parameter
1470    // already follows.
1471    let mut at = 0;
1472    let start = body.here();
1473    if boundary.receiver {
1474        body.frame
1475            .bind("self", param_slots[0], boundary.params[0], start);
1476        at = 1;
1477    }
1478    for (index, param) in decl.decl.params.iter().enumerate() {
1479        body.frame.bind(
1480            &param.name.node,
1481            param_slots[at + index],
1482            boundary.params[at + index],
1483            start,
1484        );
1485    }
1486    body.block(&decl.decl.body, Some(answer));
1487    // The epilogue is written at the *tail*, not at the block: a `return`
1488    // answers the expression the body ends with, and that is the line a
1489    // reader stopped there wants named. The block's own span begins at its
1490    // opening brace, which is the declaration's line and says nothing about
1491    // where the answer came from.
1492    //
1493    // It was not visible until issue #302. The tail used to leave its answer
1494    // in a temporary and a `copy` carried it into the answer's location, so
1495    // the instruction a caller resumed at was that copy and it was written
1496    // at the tail. Forwarding the destination removed the copy and left the
1497    // `Return` standing where it had stood, which is how a debugger session
1498    // came to name the declaration's brace instead of the call that had just
1499    // answered.
1500    let ends = decl
1501        .decl
1502        .body
1503        .tail
1504        .as_ref()
1505        .map_or(decl.decl.body.span, |tail| tail.span);
1506    let end = body.here();
1507    let clears = body.frame.pop_scope(end);
1508    body.clear(&clears, ends);
1509    body.emit(Inst::Return { src: answer.slot }, ends);
1510
1511    let reprs = body.frame.reprs().to_vec();
1512    let mut locals = body.frame.locals();
1513    // Every parameter, including a receiver bound at `param_slots[0]`, is
1514    // live for the whole call — see `Frame::close_whole_function` for the
1515    // proof — and this is the one place that both holds the parameters'
1516    // slots and knows how long the finished body is.
1517    let end = body.code.len() as Pc;
1518    Frame::close_whole_function(&mut locals, &param_slots, end);
1519    Function {
1520        module: decl.module.clone(),
1521        name,
1522        params: boundary.params.clone(),
1523        refs: RefMap::of(&reprs),
1524        reprs,
1525        returns: boundary.returns,
1526        captures: Vec::new(),
1527        code: body.code,
1528        spans: body.spans,
1529        locals,
1530        inlined: Vec::new(),
1531        span: decl.decl.span,
1532        is_async: decl.decl.is_async,
1533        stub: false,
1534    }
1535}
1536
1537/// What stands in for a declaration this pass did not lower.
1538///
1539/// Three kinds reach it, and they end differently.
1540///
1541/// One is a declaration this lowering reported a gap about, and nothing ever
1542/// runs that: a gap is an error and the program is not handed back.
1543///
1544/// The second is a declaration [`lower_entry`]'s slice left out, and that one
1545/// is in a program that *does* run. Nothing can name it: no call was emitted
1546/// to it — the fixed point is what makes that true — and it is left out of
1547/// [`Program::by_name`], so it is not an entry point either. It exists so
1548/// that function ids stay dense, which is what lets a set of ids gathered by
1549/// one pass mean the same thing in the next.
1550///
1551/// The third is a **generic declaration**, and it is in a program that runs
1552/// and is not an error. It is not a stand-in for anything: a generic
1553/// declaration is not one function, so there is nothing here for it to be.
1554/// What the program carries instead is its instantiations, each a function
1555/// of its own numbered past the declarations. This holds its number for the
1556/// same reason the second kind does, and is left out of
1557/// [`Program::by_name`] for the same reason too.
1558fn stub(decl: &Decl) -> Function {
1559    let reprs = vec![Repr::Unit];
1560    Function {
1561        module: decl.module.clone(),
1562        name: decl.name.clone(),
1563        params: Vec::new(),
1564        refs: RefMap::of(&reprs),
1565        reprs,
1566        returns: shapes::UNIT,
1567        captures: Vec::new(),
1568        code: vec![Inst::Return { src: 0 }],
1569        spans: vec![decl.decl.span],
1570        locals: Vec::new(),
1571        inlined: Vec::new(),
1572        span: decl.decl.span,
1573        is_async: false,
1574        stub: true,
1575    }
1576}
1577
1578impl Body<'_> {
1579    // ---- emitting -------------------------------------------------------
1580
1581    /// Appends one instruction and the span it came from, answering where it
1582    /// landed so a jump can be patched later.
1583    fn emit(&mut self, inst: Inst, span: Span) -> Pc {
1584        let at = self.here();
1585        self.code.push(inst);
1586        self.spans.push(span);
1587        at
1588    }
1589
1590    /// Where the next instruction will land, which is what a forward jump is
1591    /// patched to.
1592    fn here(&self) -> Pc {
1593        self.code.len() as Pc
1594    }
1595
1596    fn patch(&mut self, at: Pc, to: Pc) {
1597        match &mut self.code[at as usize] {
1598            Inst::Jump { to: target } | Inst::BranchFalse { to: target, .. } => *target = to,
1599            other => unreachable!("patched a {other:?}, which is not a jump"),
1600        }
1601    }
1602
1603    // ---- locations -------------------------------------------------------
1604
1605    /// The words a value of `layout` occupies.
1606    fn words(&self, layout: LayoutId) -> Vec<Repr> {
1607        self.pool.shapes.words(layout).to_vec()
1608    }
1609
1610    fn width(&self, layout: LayoutId) -> u32 {
1611        self.pool.shapes.width(layout)
1612    }
1613
1614    /// Whether a location of this layout holds anything a collection traces,
1615    /// or an address whose live range this lowering ends.
1616    fn holds_ref(&self, layout: LayoutId) -> bool {
1617        self.pool.shapes.holds_ref(layout)
1618    }
1619
1620    /// A run of the frame wide enough for a value of `layout`.
1621    fn alloc(&mut self, layout: LayoutId) -> Slot {
1622        let words = self.words(layout);
1623        self.frame.alloc(&words)
1624    }
1625
1626    /// A temporary location of `layout`.
1627    ///
1628    /// A temporary that holds a reference is recorded in [`Body::held`] for
1629    /// the length of its live range, so that an early exit from a loop can
1630    /// clear the ones a scope knows nothing about.
1631    fn temp(&mut self, layout: LayoutId) -> Val {
1632        let slot = self.alloc(layout);
1633        if self.holds_ref(layout) {
1634            self.hold(slot, layout);
1635        }
1636        Val::temp(slot, layout)
1637    }
1638
1639    /// Records that a temporary at `slot` is live.
1640    ///
1641    /// Any earlier entry for the same slot is dropped first. A run holds one
1642    /// value at a time — the frame only hands one out again after it has been
1643    /// freed — so a second entry for a slot supersedes the first rather than
1644    /// standing beside it, and a stale one would be a `Clear` of a location
1645    /// something else is now using.
1646    fn hold(&mut self, slot: Slot, layout: LayoutId) {
1647        self.forget(slot);
1648        self.held.push((slot, layout));
1649    }
1650
1651    /// Ends the record of the temporary at `slot`, whether or not there was
1652    /// one.
1653    fn forget(&mut self, slot: Slot) {
1654        self.held.retain(|(held, _)| *held != slot);
1655    }
1656
1657    /// Gives a location's run back without ending anything's live range.
1658    ///
1659    /// Every consumer of a *value* calls [`Body::release`] instead; this is
1660    /// for a run the lowering allocated and knows holds nothing.
1661    fn give_back(&mut self, slot: Slot, layout: LayoutId) {
1662        let width = self.width(layout);
1663        self.forget(slot);
1664        self.frame.free(slot, width);
1665    }
1666
1667    /// One [`Inst::Copy`]: ADR 0001's field-wise shallow copy, as many words
1668    /// as the layout says.
1669    fn copy(&mut self, dst: Slot, src: Slot, layout: LayoutId, span: Span) {
1670        if dst == src {
1671            return;
1672        }
1673        self.emit(Inst::Copy { dst, src, layout }, span);
1674    }
1675
1676    /// Zeroes a location's words.
1677    fn zero(&mut self, slot: Slot, layout: LayoutId, span: Span) {
1678        self.emit(Inst::Clear { slot, layout }, span);
1679    }
1680
1681    /// Puts a value in a form a location of `want` can hold.
1682    ///
1683    /// There is one conversion in the language and it is erasure, so the
1684    /// only difference this bridges is a box — and a box has two directions.
1685    /// A concrete value on its way into a `dyn` or an `Any` location is
1686    /// boxed; an erased value on its way into a location whose type is
1687    /// written is opened, which is [`Body::unbox`].
1688    ///
1689    /// Anything else is a copy of the wrong width. It is reported as a gap
1690    /// rather than emitted, because `lower` answers `Err` before the
1691    /// verifier ever sees it — which is the difference between a construct
1692    /// this lowering has not been taught and a program in the heap with the
1693    /// wrong number of words in it.
1694    fn fit(&mut self, value: Val, want: LayoutId, span: Span) -> Val {
1695        if value.layout == want {
1696            return value;
1697        }
1698        if self.is_boxed(want) {
1699            let dst = self.temp(want);
1700            self.emit(
1701                Inst::Box {
1702                    dst: dst.slot,
1703                    src: value.slot,
1704                    layout: value.layout,
1705                },
1706                span,
1707            );
1708            self.release(value, span);
1709            return dst;
1710        }
1711        if self.is_boxed(value.layout) {
1712            return self.unbox(value, want, span);
1713        }
1714        let held = self.pool.shapes.layout(value.layout).name.clone();
1715        let wanted = self.pool.shapes.layout(want).name.clone();
1716        self.errors.push(gap::gap(
1717            &format!("a `{held}` where a `{wanted}` goes, which this lowering cannot convert"),
1718            span,
1719        ));
1720        self.release(value, span);
1721        self.temp(want)
1722    }
1723
1724    /// Opens an erased value at the layout the place using it names.
1725    ///
1726    /// Where `want` comes from is the whole of what this depends on, and it
1727    /// is never invented here: it is a type the source *wrote* at the place
1728    /// the value is being used — a declared parameter, a declared return
1729    /// type, a field's declared type — or, for an operator, the layout of
1730    /// the operand beside it. A use where nothing says is a gap raised by
1731    /// the caller rather than a layout guessed here.
1732    ///
1733    /// The trap is [`Inst::Unbox`]'s: a box carries the [`LayoutId`] of what
1734    /// was put in it, and reading it as something else fails the run rather
1735    /// than reinterpreting the words. That is what makes erasure safe
1736    /// without the checker having proved anything about it.
1737    fn unbox(&mut self, value: Val, want: LayoutId, span: Span) -> Val {
1738        let dst = self.temp(want);
1739        self.emit(
1740            Inst::Unbox {
1741                dst: dst.slot,
1742                src: value.slot,
1743                layout: want,
1744            },
1745            span,
1746        );
1747        self.release(value, span);
1748        dst
1749    }
1750
1751    // ---- reading a layout ------------------------------------------------
1752
1753    /// The field `name` of a struct-shaped layout: its word offset within
1754    /// the value and its own layout.
1755    ///
1756    /// This is where a field access stops being an instruction. `l.from.x`
1757    /// is `base + Field::at` twice over, computed here and added to a slot
1758    /// number, because the fields of an inline value are *where the value
1759    /// is*.
1760    fn field_of(&self, layout: LayoutId, name: &str) -> Option<crate::layout::Field> {
1761        self.pool.shapes.layout(layout).field(name).cloned()
1762    }
1763
1764    /// The fields of a struct-shaped layout, in declaration order.
1765    fn fields_of(&self, layout: LayoutId) -> Option<Vec<crate::layout::Field>> {
1766        match &self.pool.shapes.layout(layout).shape {
1767            crate::layout::Shape::Struct { fields, .. } => Some(fields.clone()),
1768            _ => None,
1769        }
1770    }
1771
1772    /// The parts of case `index` of an enum-shaped layout, and the payload
1773    /// region's own words.
1774    ///
1775    /// A part's `at` is an offset within the payload region, which begins
1776    /// *after* the discriminant, so a part of the value is at
1777    /// `base + 1 + at`.
1778    /// How many cases an enum-shaped layout has, for sizing a switch table.
1779    fn case_count(&self, layout: LayoutId) -> Option<usize> {
1780        match &self.pool.shapes.layout(layout).shape {
1781            crate::layout::Shape::Enum { cases, .. } => Some(cases.len()),
1782            _ => None,
1783        }
1784    }
1785
1786    fn case_of(
1787        &self,
1788        layout: LayoutId,
1789        index: u32,
1790    ) -> Option<(Vec<crate::layout::Part>, Vec<Repr>)> {
1791        match &self.pool.shapes.layout(layout).shape {
1792            crate::layout::Shape::Enum { cases, payload } => cases
1793                .get(index as usize)
1794                .map(|case| (case.parts.clone(), payload.clone())),
1795            _ => None,
1796        }
1797    }
1798
1799    /// Whether a value of this layout is one heap address naming a box.
1800    ///
1801    /// A `dyn Trait` is the one this lowering builds: erasure is where a
1802    /// value stops having a static width, and a heap object is where a value
1803    /// without a static width lives.
1804    fn is_boxed(&self, layout: LayoutId) -> bool {
1805        matches!(
1806            self.pool.shapes.layout(layout).shape,
1807            crate::layout::Shape::Boxed
1808        )
1809    }
1810
1811    /// The layout of one element of a run-of-elements family.
1812    ///
1813    /// `None` for everything else, because everything else is not a run: the
1814    /// question is asked where a lowering holds a sequence's own layout and
1815    /// needs the stride, which is the element layout's width.
1816    fn element_layout(&self, layout: LayoutId) -> Option<LayoutId> {
1817        match self.pool.shapes.layout(layout).shape {
1818            crate::layout::Shape::Elements { elem, .. } => Some(elem),
1819            _ => None,
1820        }
1821    }
1822
1823    /// Whether a value of this layout is one word of scalar bits, which is
1824    /// what an instruction rather than a walk can compare.
1825    fn is_scalar(&self, layout: LayoutId) -> bool {
1826        matches!(
1827            self.pool.shapes.layout(layout).shape,
1828            crate::layout::Shape::Word(_)
1829        )
1830    }
1831
1832    /// Whether a value of this layout is a case index and nothing else.
1833    ///
1834    /// An enum with no payload is one word wide and that word is the
1835    /// discriminant, so `Kind.Space == Kind.Word` is `1 == 2`.
1836    ///
1837    /// Asked separately from [`Self::is_scalar`] because the layout is not a
1838    /// [`Shape::Word`](crate::layout::Shape::Word): the shape says what a
1839    /// value is *made of*, and an enum is made of a discriminant and a
1840    /// payload region however empty that region turns out to be. What this
1841    /// asks is narrower — whether the instruction set can compare it in one
1842    /// step.
1843    fn is_case_index(&self, layout: LayoutId) -> bool {
1844        matches!(
1845            &self.pool.shapes.layout(layout).shape,
1846            crate::layout::Shape::Enum { payload, .. } if payload.is_empty()
1847        )
1848    }
1849
1850    /// Whether `layout` is the string family.
1851    ///
1852    /// A `String` is the one heap value the language orders: `a < b` on two
1853    /// of them compares their bytes. Every other heap value the checker
1854    /// admits an operator on admits only `==` and `!=`.
1855    fn is_text(&self, layout: LayoutId) -> bool {
1856        matches!(
1857            self.pool.shapes.layout(layout).shape,
1858            crate::layout::Shape::Str
1859        )
1860    }
1861
1862    /// Ends the live range of the reference locations a scope owned.
1863    ///
1864    /// A scalar body emits nothing here, because [`Frame::pop_scope`]
1865    /// answers an empty list. A body that holds an object emits one clear
1866    /// per binding, and that clear is what keeps a static reference map from
1867    /// being a leak: the map says which slots a collection *reads*, and only
1868    /// the data can say when the value in one stopped being needed.
1869    fn clear(&mut self, locations: &[(Slot, LayoutId)], span: Span) {
1870        for (slot, layout) in locations {
1871            self.zero(*slot, *layout, span);
1872        }
1873    }
1874
1875    /// Ends a temporary's live range, clearing the location when it held
1876    /// something the collector would otherwise trace.
1877    ///
1878    /// Every consumer of a value calls this rather than freeing the run
1879    /// behind it, so a reference a body stopped needing is null from that
1880    /// instruction onwards rather than until the frame returns. It is
1881    /// unconditional for a location holding a `Ref` or an `Addr`: the run
1882    /// goes back on a free list here, and whether some later value of the
1883    /// same shape happens to overwrite it is a fact about the rest of the
1884    /// body, which this cannot see and must not assume.
1885    ///
1886    /// A borrowed location is not cleared, because it is not this
1887    /// expression's to end: a parameter, a local, or the answer outlives the
1888    /// expression that read it, and the scope that owns it clears it.
1889    fn release(&mut self, value: Val, span: Span) {
1890        if !value.temp {
1891            return;
1892        }
1893        if self.holds_ref(value.layout) {
1894            self.zero(value.slot, value.layout, span);
1895        }
1896        self.give_back(value.slot, value.layout);
1897    }
1898
1899    /// A string of the program's pool, added only if it is not already in
1900    /// it.
1901    fn string(&mut self, text: &str) -> StrId {
1902        self.pool.string(text)
1903    }
1904
1905    /// The layout of a value of `ty`, reporting the type this lowering
1906    /// cannot build one for.
1907    fn layout(&mut self, ty: &Ty, span: Span) -> Option<LayoutId> {
1908        match self.pool.shapes.of(self.checked, self.module, ty) {
1909            Some(id) => Some(id),
1910            None => {
1911                self.report(ty, span);
1912                None
1913            }
1914        }
1915    }
1916
1917    /// Says why a type has no layout here, in the words [`describe`] chooses.
1918    fn report(&mut self, ty: &Ty, span: Span) {
1919        let item = describe(&self.pool.shapes, ty, span);
1920        self.errors.push(item);
1921    }
1922
1923    // ---- reading the checker's answers -----------------------------------
1924
1925    /// The type the checker settled for `expr`, in the terms the declaration
1926    /// was written in.
1927    ///
1928    /// Inside a generic body that is a `Ty::Param`, because the checker
1929    /// walked the body once with its type parameters rigid. Almost nothing
1930    /// wants that: [`Body::ty`] is what a lowering asks, and this is for the
1931    /// two questions that are about the *declaration* rather than about the
1932    /// value — whether a receiver is a bounded type parameter, and whether an
1933    /// expression diverges.
1934    fn raw_ty(&self, expr: &Expr) -> Option<&Ty> {
1935        self.checked.facts.ty(expr.span.file, expr.id)
1936    }
1937
1938    /// The type the checker settled for `expr`, as this instantiation
1939    /// settles it.
1940    ///
1941    /// Owned rather than borrowed because a body of a generic declaration is
1942    /// lowered once per set of type arguments and the answer is built from
1943    /// the fact rather than being the fact. For a declaration that binds no
1944    /// type parameters the substitution is the identity and this is a clone.
1945    fn ty(&self, expr: &Expr) -> Option<Ty> {
1946        self.raw_ty(expr).map(|ty| self.complete(ty))
1947    }
1948
1949    /// A type written in the declaration's own terms, as this instantiation
1950    /// settles it.
1951    fn complete(&self, ty: &Ty) -> Ty {
1952        ty.instantiate(&self.generics, &self.args)
1953    }
1954
1955    /// The same as [`Body::ty`], reporting an expression the checker recorded
1956    /// nothing for.
1957    fn settled_ty(&mut self, expr: &Expr) -> Option<Ty> {
1958        match self.ty(expr) {
1959            Some(ty) => Some(ty),
1960            None => {
1961                self.errors.push(gap::gap(
1962                    "an expression the checker recorded no type for",
1963                    expr.span,
1964                ));
1965                None
1966            }
1967        }
1968    }
1969
1970    /// The layout of `expr`'s value, reporting the reason there is none.
1971    ///
1972    /// A reported failure answers the one-word `Unit` layout so that
1973    /// lowering can carry on and find the rest of what is wrong in the same
1974    /// run. The answer is never acted on: `lower` has an error and will not
1975    /// hand the program back.
1976    fn layout_of(&mut self, expr: &Expr) -> LayoutId {
1977        let Some(ty) = self.ty(expr) else {
1978            self.errors.push(gap::gap(
1979                "an expression the checker recorded no type for",
1980                expr.span,
1981            ));
1982            return shapes::UNIT;
1983        };
1984        self.layout(&ty, expr.span).unwrap_or(shapes::UNIT)
1985    }
1986
1987    /// Whether this expression leaves rather than answering: a `return`, a
1988    /// `break`, a `continue`, or a form built out of them.
1989    ///
1990    /// What it decides is whether the surrounding form copies the answer.
1991    /// Nothing is ever written to a diverging expression's location, so
1992    /// copying from it would move words that were never produced — and where
1993    /// the surrounding form wants a different layout, it would not even be
1994    /// well formed.
1995    ///
1996    /// The fact is read as it was recorded. `Ty::Never` holds no type
1997    /// parameter, so no instantiation can turn one into it or it into
1998    /// anything else, and this is asked once per stored value.
1999    fn diverges(&self, expr: &Expr) -> bool {
2000        matches!(self.raw_ty(expr), Some(Ty::Never))
2001    }
2002
2003    /// Copies an expression's answer into the location the surrounding form
2004    /// is assembling its own in.
2005    ///
2006    /// The one thing this is not is a copy in every case. A body whose
2007    /// declared return type is `dyn Trait` erases its tail on the way into
2008    /// the answer, because a declared return type is a written type and that
2009    /// is where the language's one implicit conversion happens. The answer
2010    /// is taken before any temporary and is never handed to anything else,
2011    /// so `dst == self.answer` names exactly the function's own tail and no
2012    /// nested form's destination.
2013    fn store(&mut self, dst: Dest, value: &Val, from: &Expr) {
2014        if self.diverges(from) || value.slot == dst.slot {
2015            return;
2016        }
2017        // Where the two disagree the value is erased on the way in, and
2018        // that is the language's one implicit conversion. `Body::erase`
2019        // covers the positions where a `dyn` type is *written*; this covers
2020        // the ones where the checker settled `dyn` for an expression whose
2021        // value was never put through one — the tail of a body declared
2022        // `-> dyn Trait`, an arm of an `if` in a `dyn` position.
2023        //
2024        // The source is borrowed here whatever it was: whoever called this
2025        // still owns it and will end its live range itself.
2026        if value.layout != dst.layout {
2027            let held = self.fit(
2028                Val::borrowed(value.slot, value.layout),
2029                dst.layout,
2030                from.span,
2031            );
2032            self.copy(dst.slot, held.slot, dst.layout, from.span);
2033            self.release(held, from.span);
2034            return;
2035        }
2036        self.copy(dst.slot, value.slot, dst.layout, from.span);
2037    }
2038
2039    /// A location for a value nothing will produce, so that a diverging
2040    /// expression still answers something the caller can hold.
2041    fn dead(&mut self, expr: &Expr) -> Val {
2042        let layout = self.layout_of(expr);
2043        self.temp(layout)
2044    }
2045
2046    /// Whether `id` is a declaration this pass lowered, recording it for the
2047    /// next one when it is not.
2048    ///
2049    /// A `false` is not a gap and is deliberately silent: it says the slice
2050    /// [`lower_entry`] took was too small, which is this crate's mistake to
2051    /// correct rather than the program's to answer for. The caller emits
2052    /// nothing naming `id`, the errors of this pass are thrown away, and the
2053    /// pass after it has the declaration.
2054    ///
2055    /// A whole-package lowering never sees one, because nothing is left out.
2056    fn reached(&mut self, id: FunctionId) -> bool {
2057        if self.plan.reached(id) {
2058            return true;
2059        }
2060        self.wanted.insert(id);
2061        false
2062    }
2063
2064    /// The source text a span covers, which is what an assertion quotes.
2065    ///
2066    /// `?` for a span the map does not hold, exactly as the oracle's own
2067    /// reader answers, so a message worded here and one worded there cannot
2068    /// differ even in the case neither expects.
2069    fn source_text(&self, span: Span) -> &str {
2070        self.sources
2071            .files()
2072            .find(|file| file.id == span.file)
2073            .and_then(|file| file.text.get(span.start as usize..span.end as usize))
2074            .unwrap_or("?")
2075    }
2076
2077    /// Reports a construct this lowering has not been taught, answering a
2078    /// location of the right shape so the walk can continue and report the
2079    /// rest.
2080    fn gap(&mut self, what: &str, expr: &Expr) -> Val {
2081        self.errors.push(gap::gap(what, expr.span));
2082        self.dead(expr)
2083    }
2084}