ADR-096: A Type Nothing Declares Is Refused Rather Than Lowered

Status: Accepted Date: September 15, 2026 Related: ADR-298 (NK1117, the same rule for a value), ADR-296 D17 (the emitter writes a name for a name, which is how an unknown one would reach rustc intact), ADR-285 D14 (OFFERED, Part I 2.2’s own set, which this reads)

1. Context

fn main() {
    let x: Widgit = 3
}

lowered as written is let x: Widgit = 3;, and comes back as rustc’s “cannot find type Widgit in this scope” — Part III C.1’s class, about a file nobody wrote.

A value nothing declares is NK1117 (ADR-298) — “nothing declares q“. Without the same for a type, C.1’s rule holds for one half of this language’s names and not the other.

2. Decisions

D1 — A written type name nothing accounts for is NK1135.

At the name, in this language’s words, with the misspelling named.

D2 — The known set is built from what the compiler already knows, not from a list.

OFFERED is Part I 2.2’s own set and already answers “does as name a type this language has”; the ledger’s types map is every type this program and std declare, under both the qualified key and its last segment, because a library writes the module in front and a caller writes the suffix; and the declaration around the name contributes its type parameters. A list maintained beside those would be a second thing to forget, and forgetting it refuses a correct program.

What is left is a short table of names the emitter writes that no ledger declares — Part I 2.2’s numeric surface beyond OFFERED’s four, the collections the prelude provides, and the hulls.

D3 — A qualified name is somebody else’s question.

http::Response names a package’s type, and whether this build can see that package is ADR-286 D11’s, with a message of its own. Saying “nothing declares it” about a name a dependency does declare would be Part III C.4 — a correct program refused — so this walk is silent about every name with a :: in it.

D4 — A walk of its own, beside dsl, views and traits.

It asks about a written name rather than about a value’s type, so it needs the item tree and neither the scope stack nor the inference. Every position a type can stand in is read: a parameter, a result, a struct’s field, an enum variant’s payload in both shapes, a trait method’s signature, an impl method’s, a let’s annotation, and every argument nested inside any of those.

3. Consequences

A refusal moves from the backend into this compiler. A specification block or a program that names a type nothing declares was already rustc’s “cannot find … in this scope”, about the generated file; it is now refused at the name, in this language’s words, which is the whole of what C.1 asks for. A type name the language does not have — List[Fortune] for Vec[Fortune] — is caught the same way.

4. What this does not decide

This site is open source. Improve this page.