ADR-183: A Path’s Head Is One of Five Things, and a Name That Is None of Them Is Refused

Status: Superseded by ADR-286 — its D1-D5 are D31-D35 there Date: September 21, 2026 Target Version: Nikaia 0.0.132 Closes: #141 (a path whose head names nothing is not refused), which is the second half of NK1171 Related: ADR-051 (NK1117, nothing declares this name), ADR-010 D1 (absence is read fail-closed, and a wrong value is worse than a missing one), ADR-104 (a description is reviewed like code), ADR-140 D5 (a module nothing describes yet is left alone)


1. Context

Op::Mul beside enum Op { Add, Sub } is NK1171 since the compiler learned to compare the name against the declaration it had already read. nowhere::wobble was not refused at all, and what the reader got was the language below:

failed to resolve: use of unresolved module or unlinked crate `nowhere`

Crate is not a word this language has, and the file it is about is one nobody wrote — Part III C.1. The entry that recorded it also recorded why it stayed open, and the reason was good: a module of a package, an item of a foreign crate and a name no ledger has been told about all look the same from inside the checker — an absent key — so refusing on absence would refuse correct programs, which C.4 forbids.

And the measurement is what made it answerable. Instrumenting the path arm over the whole corpus turned up seven distinct paths used as values — Summary::merge, Report::merge, Refused::NoStatement, Refused::NoDatabase, Op::Times, Op::Divide, Json::Null — and not one has a head this compiler has not read.

2. Decisions

D1 — A head is one of five things, and the list is written down.

Every one of the five is something this compiler has already read — three of them were written down somewhere before this record and the walk that asks them in order is what was missing. So the refusal is not this key is absent; it is this word answers to none of the five things a word in front of a :: may be.

D2 — A ledger that records anything under head:: answers for the head.

A described crate is a list of its items, and no table carries the crate’s own word on a line of its own. So the last question the walk asks is a prefix: if either ledger has any key beginning head::, the head is one this build was told about, whatever the member turns out to be.

Without this, nikaia describe’s own output would have been refused by the compiler that asked for it.

D3 — The way out names a file, three times over.

Part III C.2: a way out that cannot be taken is not one. Each of the three the message offers is a file the reader writes — a .nika file beside this one for a module, a [dependencies] line for a package, nikaia describe <head> for a foreign crate — which is the whole difference between this and unresolved module or unlinked crate, where the reader is told what failed and not what to do.

D4 — It fails open, and the direction is deliberate.

The list is a list of permissions and not of prohibitions: a head that answers any one of them is left alone, and the refusal fires only where all five are silent. That is ADR-010 D1’s polarity applied to a refusal rather than to a claim — a missing refusal costs a rustc message, and a wrong one costs a correct program.

D5 — A head the package’s other files declare is a head.

The files of a package share one namespace (Part I 9.1), so Shade::Even in main.nika names an enum that may stand in shades.nika — and the tables D1 asks first are this unit’s. Written against those alone the refusal is a correct program refused, which is the one thing this checker may never do, and the same shape ADR-182’s package had one construct over.

Read off the item tree of the other files and not off a ledger, because a ledger records what a type promises and what is asked here is only that the word was written down: a private enum a neighbouring file declares is a head, whatever its contract says.

3. Consequences

4. What this does not decide

5. What is built

All of D1 to D5, at 0.0.132.

This site is open source. Improve this page.