Skip to main content

zerodds_lang_rules/
coverage.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! The completeness table. Spec §4.1.
4//!
5//! One cell per construct and language, each stating the rule that
6//! covers it or that it is deliberately uncovered, with a reason.
7//!
8//! The table has no catch-all arm. A construct added to the common AST
9//! without a decision here is a compile error, not a language backend
10//! that silently emits nothing for it.
11
12use zerodds_lang_cst::Language;
13
14/// The constructs a rule catalogue has to account for.
15///
16/// The same 21 `zerodds-ast-1.0` §8.2 rules on, so the two tables can be
17/// read against each other.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub enum ConstructKind {
20    /// A module.
21    Module,
22    /// A primitive type.
23    Primitive,
24    /// `fixed<d,s>`.
25    Fixed,
26    /// `string` and `wstring`.
27    StringType,
28    /// `sequence<T>`.
29    Sequence,
30    /// An array.
31    Array,
32    /// `map<K,V>`.
33    Map,
34    /// A struct.
35    Structure,
36    /// A union.
37    Union,
38    /// An enumeration.
39    Enumeration,
40    /// A bitmask.
41    Bitmask,
42    /// A bitset.
43    Bitset,
44    /// A typedef.
45    Alias,
46    /// A valuetype.
47    Valuetype,
48    /// A boxed value.
49    ValueBox,
50    /// A native type.
51    Native,
52    /// `any`.
53    Any,
54    /// `ValueBase`.
55    ValueBase,
56    /// An object reference.
57    ObjectRef,
58    /// An annotation type.
59    AnnotationType,
60    /// A constant.
61    Const,
62    /// An interface.
63    Interface,
64    /// An exception.
65    Exception,
66}
67
68impl ConstructKind {
69    /// Every construct the table covers.
70    pub const ALL: [Self; 23] = [
71        Self::Module,
72        Self::Primitive,
73        Self::Fixed,
74        Self::StringType,
75        Self::Sequence,
76        Self::Array,
77        Self::Map,
78        Self::Structure,
79        Self::Union,
80        Self::Enumeration,
81        Self::Bitmask,
82        Self::Bitset,
83        Self::Alias,
84        Self::Valuetype,
85        Self::ValueBox,
86        Self::Native,
87        Self::Any,
88        Self::ValueBase,
89        Self::ObjectRef,
90        Self::AnnotationType,
91        Self::Const,
92        Self::Interface,
93        Self::Exception,
94    ];
95
96    /// The name a table column uses.
97    #[must_use]
98    pub const fn as_str(self) -> &'static str {
99        match self {
100            Self::Module => "module",
101            Self::Primitive => "primitive",
102            Self::Fixed => "fixed",
103            Self::StringType => "string",
104            Self::Sequence => "sequence",
105            Self::Array => "array",
106            Self::Map => "map",
107            Self::Structure => "struct",
108            Self::Union => "union",
109            Self::Enumeration => "enum",
110            Self::Bitmask => "bitmask",
111            Self::Bitset => "bitset",
112            Self::Alias => "typedef",
113            Self::Valuetype => "valuetype",
114            Self::ValueBox => "valuebox",
115            Self::Native => "native",
116            Self::Any => "any",
117            Self::ValueBase => "valuebase",
118            Self::ObjectRef => "object reference",
119            Self::AnnotationType => "annotation type",
120            Self::Const => "const",
121            Self::Interface => "interface",
122            Self::Exception => "exception",
123        }
124    }
125}
126
127/// What a cell of the table says.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum Coverage {
130    /// A rule covers it, named here.
131    Rule(&'static str),
132    /// Deliberately uncovered, with the reason.
133    Uncovered(&'static str),
134}
135
136impl Coverage {
137    /// Whether a rule covers this cell.
138    #[must_use]
139    pub const fn is_covered(self) -> bool {
140        matches!(self, Self::Rule(_))
141    }
142
143    /// The rule's name, or the reason it has none.
144    #[must_use]
145    pub const fn reason(self) -> &'static str {
146        match self {
147            Self::Rule(name) | Self::Uncovered(name) => name,
148        }
149    }
150}
151
152/// What covers `construct` in `language`.
153///
154/// Exhaustive over both, with no catch-all: adding a construct or a
155/// language is a compile error here until a decision is written down.
156#[must_use]
157#[allow(clippy::too_many_lines)]
158pub const fn coverage_of(construct: ConstructKind, language: Language) -> Coverage {
159    use ConstructKind as C;
160    use Language as L;
161
162    match (construct, language) {
163        // -- Rust: every construct has a rule ---------------------------
164        (C::Structure, L::Rust) => Coverage::Rule("struct-to-struct"),
165        (C::Enumeration, L::Rust) => Coverage::Rule("enum-to-enum"),
166        (C::Alias, L::Rust) => Coverage::Rule("alias-to-type-alias"),
167        (C::Union, L::Rust) => Coverage::Rule("union-to-enum"),
168        (C::Bitmask, L::Rust) => Coverage::Rule("bitmask-to-struct"),
169        (C::Bitset, L::Rust) => Coverage::Rule("bitset-to-struct"),
170        (C::Valuetype, L::Rust) => Coverage::Rule("valuetype-to-struct"),
171        (C::Module, L::Rust) => Coverage::Rule("module-to-mod"),
172        (C::Const, L::Rust) => Coverage::Rule("const-to-const"),
173        (C::Exception, L::Rust) => Coverage::Rule("exception-to-struct"),
174        (C::Interface, L::Rust) => Coverage::Rule("interface-to-trait"),
175        (C::Native, L::Rust) => Coverage::Rule("native-to-alias"),
176        // The four that are not declarations of their own: a member's
177        // type becomes a Rust type where the member is materialised,
178        // which is the `member-to-field` rule's doing.
179        (C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed, L::Rust) => {
180            Coverage::Rule("member-to-field")
181        }
182        (C::ValueBox, L::Rust) => Coverage::Rule("member-to-field"),
183        (C::ObjectRef, L::Rust) => Coverage::Uncovered("object references belong to the RPC arc"),
184        (C::Any, L::Rust) => {
185            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
186        }
187        (C::ValueBase, L::Rust) => Coverage::Uncovered(
188            "which valuetype arrives is a run-time question; the CORBA arc owns it",
189        ),
190        (C::AnnotationType, L::Rust) => {
191            Coverage::Uncovered("no Rust equivalent; nothing is emitted")
192        }
193
194        // -- C: the second column, and the pattern the rest follow ------
195        //
196        // A module is covered here where it is uncovered in C++ and
197        // Java: C has no namespaces, so `module-to-prefix` is not a
198        // placeholder for a scope rule — flattening the scoped name onto
199        // every identifier *is* what a module becomes.
200        (C::Module, L::C) => Coverage::Rule("module-to-prefix"),
201        (C::Structure, L::C) => Coverage::Rule("struct-to-struct"),
202        (C::Enumeration, L::C) => Coverage::Rule("enum-to-enum"),
203        (C::Alias, L::C) => Coverage::Rule("alias-to-typedef"),
204        (C::Union, L::C) => Coverage::Rule("union-to-union"),
205        (C::Bitmask, L::C) => Coverage::Rule("bitmask-to-enum"),
206        (C::Bitset, L::C) => Coverage::Rule("bitset-to-struct"),
207        (C::Valuetype, L::C) => Coverage::Rule("valuetype-to-struct"),
208        (C::Const, L::C) => Coverage::Rule("const-to-const"),
209        (C::Exception, L::C) => Coverage::Rule("exception-to-struct"),
210        (C::Native, L::C) => Coverage::Rule("native-to-typedef"),
211        // The six that are not declarations of their own. C has no
212        // generics, so each becomes a declared support type where the
213        // member is materialised — which is still `member-to-member`'s
214        // doing, the same way `member-to-field` owns them in Rust.
215        (
216            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
217            L::C,
218        ) => Coverage::Rule("member-to-member"),
219        (C::ObjectRef, L::C) => Coverage::Uncovered("object references belong to the RPC arc"),
220        (C::Any, L::C) => {
221            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
222        }
223        (C::ValueBase, L::C) => Coverage::Uncovered(
224            "which valuetype arrives is a run-time question; the CORBA arc owns it",
225        ),
226        (C::AnnotationType, L::C) => Coverage::Uncovered("no C equivalent; nothing is emitted"),
227        // Uncovered and not merely unwritten: a C interface is a struct
228        // of function pointers, and `zerodds_lang_cst::c::Type` has no
229        // function-pointer form — the name sits inside the declarator,
230        // which the tree cannot express. Adding the rule before the tree
231        // can hold its output would be a catalogue claiming coverage
232        // that materialises to nothing.
233        (C::Interface, L::C) => {
234            Coverage::Uncovered("the C CST has no function-pointer type to declare one with")
235        }
236
237        // -- the two catalogues that follow ------------------------------
238        //
239        // Named rather than left out: a table that listed only what is
240        // done would read as a table that is done.
241        (C::Module, L::Cpp) => Coverage::Uncovered("module-to-namespace, not yet written"),
242        (C::Module, L::Java) => Coverage::Uncovered("module-to-package, not yet written"),
243        (
244            C::Primitive
245            | C::Fixed
246            | C::StringType
247            | C::Sequence
248            | C::Array
249            | C::Map
250            | C::Structure
251            | C::Union
252            | C::Enumeration
253            | C::Bitmask
254            | C::Bitset
255            | C::Alias
256            | C::Valuetype
257            | C::ValueBox
258            | C::Native
259            | C::Any
260            | C::ValueBase
261            | C::ObjectRef
262            | C::AnnotationType
263            | C::Const
264            | C::Interface
265            | C::Exception,
266            L::Cpp | L::Java,
267        ) => Coverage::Uncovered("catalogue not yet written for this language"),
268        // -- C#: every construct that has a data form ---------------------
269        (C::Structure, L::CSharp) => Coverage::Rule("struct-to-class"),
270        (C::Enumeration, L::CSharp) => Coverage::Rule("enum-to-enum"),
271        (C::Alias, L::CSharp) => Coverage::Rule("alias-to-using"),
272        (C::Union, L::CSharp) => Coverage::Rule("union-to-class"),
273        (C::Bitmask, L::CSharp) => Coverage::Rule("bitmask-to-flags-enum"),
274        (C::Bitset, L::CSharp) => Coverage::Rule("bitset-to-class"),
275        (C::Valuetype, L::CSharp) => Coverage::Rule("valuetype-to-class"),
276        (C::Module, L::CSharp) => Coverage::Rule("module-to-namespace"),
277        (C::Const, L::CSharp) => Coverage::Rule("const-to-const"),
278        (C::Exception, L::CSharp) => Coverage::Rule("exception-to-class"),
279        (C::Interface, L::CSharp) => Coverage::Rule("interface-to-interface"),
280        (C::Native, L::CSharp) => Coverage::Rule("native-to-alias"),
281        (C::Primitive, L::CSharp) => Coverage::Rule("member-to-field"),
282        (C::StringType, L::CSharp) => Coverage::Rule("member-to-field"),
283        (C::Sequence, L::CSharp) => Coverage::Rule("member-to-field"),
284        (C::Array, L::CSharp) => Coverage::Rule("member-to-field"),
285        (C::Map, L::CSharp) => Coverage::Rule("member-to-field"),
286        (C::Fixed, L::CSharp) => Coverage::Rule("member-to-field"),
287        (C::ValueBox, L::CSharp) => Coverage::Rule("member-to-field"),
288        (C::Any, L::CSharp) => Coverage::Uncovered(
289            "an `any` needs the dynamic type system, which is the reflective arc",
290        ),
291        (C::ValueBase, L::CSharp) => {
292            Coverage::Uncovered("no C# form; a valuetype base is not a declaration of its own")
293        }
294        (C::ObjectRef, L::CSharp) => Coverage::Uncovered("object references belong to the RPC arc"),
295        (C::AnnotationType, L::CSharp) => Coverage::Uncovered("an annotation declares no data"),
296
297        // -- Python -------------------------------------------------------
298        (C::Structure, L::Python) => Coverage::Rule("struct-to-dataclass"),
299        (C::Enumeration, L::Python) => Coverage::Rule("enum-to-intenum"),
300        (C::Alias, L::Python) => Coverage::Rule("alias-to-comment"),
301        (C::Union, L::Python) => Coverage::Rule("union-to-dataclass"),
302        (C::Bitmask, L::Python) => Coverage::Rule("bitmask-to-intflag"),
303        (C::Bitset, L::Python) => Coverage::Rule("bitset-to-dataclass"),
304        (C::Valuetype, L::Python) => Coverage::Rule("valuetype-to-dataclass"),
305        (C::Module, L::Python) => Coverage::Rule("module-to-class"),
306        (C::Const, L::Python) => Coverage::Rule("const-to-final"),
307        (C::Exception, L::Python) => Coverage::Rule("exception-to-dataclass"),
308        (C::Interface, L::Python) => Coverage::Uncovered(
309            "the rule fires and materialises nothing; an IDL interface has no data form in a types-only column",
310        ),
311        (C::Native, L::Python) => Coverage::Rule("native-to-comment"),
312        (C::Primitive, L::Python) => Coverage::Rule("member-to-field"),
313        (C::StringType, L::Python) => Coverage::Rule("member-to-field"),
314        (C::Sequence, L::Python) => Coverage::Rule("member-to-field"),
315        (C::Array, L::Python) => Coverage::Rule("member-to-field"),
316        (C::Map, L::Python) => Coverage::Rule("member-to-field"),
317        (C::Fixed, L::Python) => Coverage::Rule("member-to-field"),
318        (C::ValueBox, L::Python) => Coverage::Rule("member-to-field"),
319        (C::Any, L::Python) => Coverage::Uncovered(
320            "an `any` needs the dynamic type system, which is the reflective arc",
321        ),
322        (C::ValueBase, L::Python) => {
323            Coverage::Uncovered("no Python form; a valuetype base is not a declaration of its own")
324        }
325        (C::ObjectRef, L::Python) => Coverage::Uncovered("object references belong to the RPC arc"),
326        (C::AnnotationType, L::Python) => Coverage::Uncovered("an annotation declares no data"),
327
328        // -- TypeScript ---------------------------------------------------
329        (C::Structure, L::TypeScript) => Coverage::Rule("struct-to-interface"),
330        (C::Enumeration, L::TypeScript) => Coverage::Rule("enum-to-const-object"),
331        (C::Alias, L::TypeScript) => Coverage::Rule("alias-to-type-alias"),
332        (C::Union, L::TypeScript) => Coverage::Rule("union-to-discriminated-union"),
333        (C::Bitmask, L::TypeScript) => Coverage::Rule("bitmask-to-const-object"),
334        (C::Bitset, L::TypeScript) => Coverage::Rule("bitset-to-interface"),
335        (C::Valuetype, L::TypeScript) => Coverage::Rule("valuetype-to-interface"),
336        (C::Module, L::TypeScript) => Coverage::Rule("module-to-namespace"),
337        (C::Const, L::TypeScript) => Coverage::Rule("const-to-const"),
338        (C::Exception, L::TypeScript) => Coverage::Rule("exception-to-interface"),
339        (C::Interface, L::TypeScript) => Coverage::Rule("interface-to-interface"),
340        (C::Native, L::TypeScript) => Coverage::Rule("native-to-type-alias"),
341        (C::Primitive, L::TypeScript) => Coverage::Rule("member-to-property"),
342        (C::StringType, L::TypeScript) => Coverage::Rule("member-to-property"),
343        (C::Sequence, L::TypeScript) => Coverage::Rule("member-to-property"),
344        (C::Array, L::TypeScript) => Coverage::Rule("member-to-property"),
345        (C::Map, L::TypeScript) => Coverage::Rule("member-to-property"),
346        (C::Fixed, L::TypeScript) => Coverage::Rule("member-to-property"),
347        (C::ValueBox, L::TypeScript) => Coverage::Rule("member-to-property"),
348        (C::Any, L::TypeScript) => Coverage::Uncovered(
349            "an `any` needs the dynamic type system, which is the reflective arc",
350        ),
351        (C::ValueBase, L::TypeScript) => Coverage::Uncovered(
352            "no TypeScript form; a valuetype base is not a declaration of its own",
353        ),
354        (C::ObjectRef, L::TypeScript) => {
355            Coverage::Uncovered("object references belong to the RPC arc")
356        }
357        (C::AnnotationType, L::TypeScript) => Coverage::Uncovered("an annotation declares no data"),
358
359        // -- Go -----------------------------------------------------------
360        //
361        // A module is covered here as it is in C and for the same
362        // reason: a Go package is a directory, so nested IDL modules
363        // cannot nest inside one generated file, and flattening the
364        // scoped name onto every identifier *is* what a module becomes.
365        // An interface is covered here and not in C, because a Go
366        // interface is a method set with names and the C tree has no
367        // function-pointer type to write one with.
368        (C::Module, L::Go) => Coverage::Rule("module-to-prefix"),
369        (C::Structure, L::Go) => Coverage::Rule("struct-to-struct"),
370        (C::Enumeration, L::Go) => Coverage::Rule("enum-to-type"),
371        (C::Alias, L::Go) => Coverage::Rule("alias-to-alias"),
372        (C::Union, L::Go) => Coverage::Rule("union-to-struct"),
373        (C::Bitmask, L::Go) => Coverage::Rule("bitmask-to-type"),
374        (C::Bitset, L::Go) => Coverage::Rule("bitset-to-struct"),
375        (C::Valuetype, L::Go) => Coverage::Rule("valuetype-to-struct"),
376        (C::Const, L::Go) => Coverage::Rule("const-to-const"),
377        (C::Exception, L::Go) => Coverage::Rule("exception-to-struct"),
378        (C::Native, L::Go) => Coverage::Rule("native-to-alias"),
379        (C::Interface, L::Go) => Coverage::Rule("interface-to-interface"),
380        // The seven that are not declarations of their own. Go writes
381        // `[]T`, `[N]T` and `string` where the member is, so each
382        // becomes a type at the point of use — which is
383        // `member-to-field`'s doing, the same way it owns them in Rust.
384        (
385            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
386            L::Go,
387        ) => Coverage::Rule("member-to-field"),
388        (C::ObjectRef, L::Go) => Coverage::Uncovered("object references belong to the RPC arc"),
389        (C::Any, L::Go) => Coverage::Uncovered(
390            "`any` carries its type at run time; Go's own `any` would compile and \
391             there would be no wire form behind it",
392        ),
393        (C::ValueBase, L::Go) => Coverage::Uncovered(
394            "which valuetype arrives is a run-time question; the CORBA arc owns it",
395        ),
396        (C::AnnotationType, L::Go) => Coverage::Uncovered("an annotation declares no data"),
397
398        // -- OCaml --------------------------------------------------------
399        //
400        // A module flattens as it does in C and Go, and for a reason
401        // neither of those has: OCaml resolves a cycle with an
402        // `and`-joined group, and such a group cannot cross a
403        // `module … struct … end` boundary, while IDL puts no
404        // restriction on where a cycle closes.
405        (C::Module, L::OCaml) => Coverage::Rule("module-to-prefix"),
406        (C::Structure, L::OCaml) => Coverage::Rule("struct-to-record"),
407        (C::Enumeration, L::OCaml) => Coverage::Rule("enum-to-variant"),
408        (C::Alias, L::OCaml) => Coverage::Rule("alias-to-abbreviation"),
409        (C::Union, L::OCaml) => Coverage::Rule("union-to-record"),
410        (C::Bitmask, L::OCaml) => Coverage::Rule("bitmask-to-abbreviation"),
411        (C::Bitset, L::OCaml) => Coverage::Rule("bitset-to-record"),
412        (C::Valuetype, L::OCaml) => Coverage::Rule("valuetype-to-record"),
413        (C::Const, L::OCaml) => Coverage::Rule("const-to-let"),
414        (C::Exception, L::OCaml) => Coverage::Rule("exception-to-record"),
415        (C::Native, L::OCaml) => Coverage::Rule("native-to-abbreviation"),
416        (C::Interface, L::OCaml) => Coverage::Rule("interface-to-class-type"),
417        // The seven that are not declarations of their own: an OCaml
418        // `array`, `option` and `string` are written where the member is.
419        (
420            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
421            L::OCaml,
422        ) => Coverage::Rule("member-to-field"),
423        (C::ObjectRef, L::OCaml) => Coverage::Uncovered("object references belong to the RPC arc"),
424        (C::Any, L::OCaml) => {
425            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
426        }
427        (C::ValueBase, L::OCaml) => Coverage::Uncovered(
428            "which valuetype arrives is a run-time question; the CORBA arc owns it",
429        ),
430        (C::AnnotationType, L::OCaml) => Coverage::Uncovered("an annotation declares no data"),
431
432        // -- Ada ---------------------------------------------------------
433        //
434        // A module flattens with `_` and a package would nest: GNAT ties a
435        // compilation unit to a file name, so one generated spec is one
436        // package.
437        (C::Module, L::Ada) => Coverage::Rule("module-to-prefix"),
438        (C::Structure, L::Ada) => Coverage::Rule("struct-to-record"),
439        (C::Enumeration, L::Ada) => Coverage::Rule("enum-to-type"),
440        (C::Alias, L::Ada) => Coverage::Rule("alias-to-subtype"),
441        (C::Union, L::Ada) => Coverage::Rule("union-to-record"),
442        (C::Bitmask, L::Ada) => Coverage::Rule("bitmask-to-type"),
443        (C::Bitset, L::Ada) => Coverage::Rule("bitset-to-record"),
444        (C::Valuetype, L::Ada) => Coverage::Rule("valuetype-to-record"),
445        (C::Const, L::Ada) => Coverage::Rule("const-to-constant"),
446        (C::Exception, L::Ada) => Coverage::Rule("exception-to-record"),
447        (C::Native, L::Ada) => Coverage::Rule("native-to-type"),
448        (C::Interface, L::Ada) => Coverage::Rule("interface-to-interface"),
449        // The seven that are not declarations of their own: each becomes
450        // a type at the point of use, which is the member rule's doing.
451        (
452            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
453            L::Ada,
454        ) => Coverage::Rule("member-to-component"),
455        (C::ObjectRef, L::Ada) => Coverage::Uncovered("object references belong to the RPC arc"),
456        (C::Any, L::Ada) => {
457            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
458        }
459        (C::ValueBase, L::Ada) => Coverage::Uncovered(
460            "which valuetype arrives is a run-time question; the CORBA arc owns it",
461        ),
462        (C::AnnotationType, L::Ada) => Coverage::Uncovered("an annotation declares no data"),
463
464        // -- D -----------------------------------------------------------
465        //
466        // A module flattens with `_`: D has real modules and one module is one
467        // file, so nested IDL modules cannot each be a D module here.
468        (C::Module, L::D) => Coverage::Rule("module-to-prefix"),
469        (C::Structure, L::D) => Coverage::Rule("struct-to-struct"),
470        (C::Enumeration, L::D) => Coverage::Rule("enum-to-enum"),
471        (C::Alias, L::D) => Coverage::Rule("alias-to-alias"),
472        (C::Union, L::D) => Coverage::Rule("union-to-struct"),
473        (C::Bitmask, L::D) => Coverage::Rule("bitmask-to-alias"),
474        (C::Bitset, L::D) => Coverage::Rule("bitset-to-struct"),
475        (C::Valuetype, L::D) => Coverage::Rule("valuetype-to-struct"),
476        (C::Const, L::D) => Coverage::Rule("const-to-const"),
477        (C::Exception, L::D) => Coverage::Rule("exception-to-struct"),
478        (C::Native, L::D) => Coverage::Rule("native-to-alias"),
479        (C::Interface, L::D) => Coverage::Rule("interface-to-interface"),
480        // The seven that are not declarations of their own: each becomes
481        // a type at the point of use, which is the member rule's doing.
482        (
483            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
484            L::D,
485        ) => Coverage::Rule("member-to-field"),
486        (C::ObjectRef, L::D) => Coverage::Uncovered("object references belong to the RPC arc"),
487        (C::Any, L::D) => Coverage::Uncovered(
488            "`any` carries its type at run time; this language has a type that would \
489             hold it and no wire form behind it",
490        ),
491        (C::ValueBase, L::D) => Coverage::Uncovered(
492            "which valuetype arrives is a run-time question; the CORBA arc owns it",
493        ),
494        (C::AnnotationType, L::D) => Coverage::Uncovered("an annotation declares no data"),
495
496        // -- Elixir ------------------------------------------------------
497        //
498        // A module **nests**, which no other flattening column can do: an Elixir
499        // module name is a dotted atom and `Common.Util.Location` is a
500        // genuine scope, not a flattened name.
501        (C::Module, L::Elixir) => Coverage::Rule("module-to-module"),
502        (C::Structure, L::Elixir) => Coverage::Rule("struct-to-module"),
503        (C::Enumeration, L::Elixir) => Coverage::Rule("enum-to-module"),
504        (C::Alias, L::Elixir) => Coverage::Rule("alias-to-type"),
505        (C::Union, L::Elixir) => Coverage::Rule("union-to-module"),
506        (C::Bitmask, L::Elixir) => Coverage::Rule("bitmask-to-module"),
507        (C::Bitset, L::Elixir) => Coverage::Rule("bitset-to-module"),
508        (C::Valuetype, L::Elixir) => Coverage::Rule("valuetype-to-module"),
509        (C::Const, L::Elixir) => Coverage::Rule("const-to-function"),
510        (C::Exception, L::Elixir) => Coverage::Rule("exception-to-module"),
511        (C::Native, L::Elixir) => Coverage::Rule("native-to-type"),
512        (C::Interface, L::Elixir) => Coverage::Rule("interface-to-behaviour"),
513        // The seven that are not declarations of their own: each becomes
514        // a type at the point of use, which is the member rule's doing.
515        (
516            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
517            L::Elixir,
518        ) => Coverage::Rule("member-to-field"),
519        (C::ObjectRef, L::Elixir) => Coverage::Uncovered("object references belong to the RPC arc"),
520        (C::Any, L::Elixir) => Coverage::Uncovered(
521            "`any` carries its type at run time; this language has a type that would \
522             hold it and no wire form behind it",
523        ),
524        (C::ValueBase, L::Elixir) => Coverage::Uncovered(
525            "which valuetype arrives is a run-time question; the CORBA arc owns it",
526        ),
527        (C::AnnotationType, L::Elixir) => Coverage::Uncovered("an annotation declares no data"),
528
529        // -- Julia -------------------------------------------------------
530        //
531        // A module flattens with `_`: Julia resolves a name in a module in
532        // declaration order, and a nested module would put a forward
533        // reference beyond reach.
534        (C::Module, L::Julia) => Coverage::Rule("module-to-prefix"),
535        (C::Structure, L::Julia) => Coverage::Rule("struct-to-struct"),
536        (C::Enumeration, L::Julia) => Coverage::Rule("enum-to-enum"),
537        (C::Alias, L::Julia) => Coverage::Rule("alias-to-const"),
538        (C::Union, L::Julia) => Coverage::Rule("union-to-struct"),
539        (C::Bitmask, L::Julia) => Coverage::Rule("bitmask-to-const"),
540        (C::Bitset, L::Julia) => Coverage::Rule("bitset-to-struct"),
541        (C::Valuetype, L::Julia) => Coverage::Rule("valuetype-to-struct"),
542        (C::Const, L::Julia) => Coverage::Rule("const-to-const"),
543        (C::Exception, L::Julia) => Coverage::Rule("exception-to-struct"),
544        (C::Native, L::Julia) => Coverage::Rule("native-to-const"),
545        (C::Interface, L::Julia) => Coverage::Rule("interface-to-abstract"),
546        // The seven that are not declarations of their own: each becomes
547        // a type at the point of use, which is the member rule's doing.
548        (
549            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
550            L::Julia,
551        ) => Coverage::Rule("member-to-field"),
552        (C::ObjectRef, L::Julia) => Coverage::Uncovered("object references belong to the RPC arc"),
553        (C::Any, L::Julia) => Coverage::Uncovered(
554            "`any` carries its type at run time; this language has a type that would \
555             hold it and no wire form behind it",
556        ),
557        (C::ValueBase, L::Julia) => Coverage::Uncovered(
558            "which valuetype arrives is a run-time question; the CORBA arc owns it",
559        ),
560        (C::AnnotationType, L::Julia) => Coverage::Uncovered("an annotation declares no data"),
561
562        // -- Lua ---------------------------------------------------------
563        //
564        // A module becomes a table, which is Lua's only scope.
565        (C::Module, L::Lua) => Coverage::Rule("module-to-table"),
566        (C::Structure, L::Lua) => Coverage::Rule("struct-to-table"),
567        (C::Enumeration, L::Lua) => Coverage::Rule("enum-to-table"),
568        (C::Alias, L::Lua) => Coverage::Rule("alias-to-entry"),
569        (C::Union, L::Lua) => Coverage::Rule("union-to-table"),
570        (C::Bitmask, L::Lua) => Coverage::Rule("bitmask-to-table"),
571        (C::Bitset, L::Lua) => Coverage::Rule("bitset-to-table"),
572        (C::Valuetype, L::Lua) => Coverage::Rule("valuetype-to-table"),
573        (C::Const, L::Lua) => Coverage::Rule("const-to-field"),
574        (C::Exception, L::Lua) => Coverage::Rule("exception-to-table"),
575        (C::Native, L::Lua) => Coverage::Rule("native-to-table"),
576        (C::Interface, L::Lua) => Coverage::Rule("interface-to-table"),
577        // The seven that are not declarations of their own: each becomes
578        // a type at the point of use, which is the member rule's doing.
579        (
580            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
581            L::Lua,
582        ) => Coverage::Rule("member-to-entry"),
583        (C::ObjectRef, L::Lua) => Coverage::Uncovered("object references belong to the RPC arc"),
584        (C::Any, L::Lua) => Coverage::Uncovered(
585            "`any` carries its type at run time; this language has a type that would \
586             hold it and no wire form behind it",
587        ),
588        (C::ValueBase, L::Lua) => Coverage::Uncovered(
589            "which valuetype arrives is a run-time question; the CORBA arc owns it",
590        ),
591        (C::AnnotationType, L::Lua) => Coverage::Uncovered("an annotation declares no data"),
592
593        // -- Nim ---------------------------------------------------------
594        //
595        // A module flattens with `_`: a Nim module is a file, so nested IDL
596        // modules cannot nest in one generated file.
597        (C::Module, L::Nim) => Coverage::Rule("module-to-prefix"),
598        (C::Structure, L::Nim) => Coverage::Rule("struct-to-object"),
599        (C::Enumeration, L::Nim) => Coverage::Rule("enum-to-enum"),
600        (C::Alias, L::Nim) => Coverage::Rule("alias-to-alias"),
601        (C::Union, L::Nim) => Coverage::Rule("union-to-object"),
602        (C::Bitmask, L::Nim) => Coverage::Rule("bitmask-to-alias"),
603        (C::Bitset, L::Nim) => Coverage::Rule("bitset-to-object"),
604        (C::Valuetype, L::Nim) => Coverage::Rule("valuetype-to-object"),
605        (C::Const, L::Nim) => Coverage::Rule("const-to-const"),
606        (C::Exception, L::Nim) => Coverage::Rule("exception-to-object"),
607        (C::Native, L::Nim) => Coverage::Rule("native-to-alias"),
608        (C::Interface, L::Nim) => Coverage::Rule("interface-to-object"),
609        // The seven that are not declarations of their own: each becomes
610        // a type at the point of use, which is the member rule's doing.
611        (
612            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
613            L::Nim,
614        ) => Coverage::Rule("member-to-field"),
615        (C::ObjectRef, L::Nim) => Coverage::Uncovered("object references belong to the RPC arc"),
616        (C::Any, L::Nim) => Coverage::Uncovered(
617            "`any` carries its type at run time; this language has a type that would \
618             hold it and no wire form behind it",
619        ),
620        (C::ValueBase, L::Nim) => Coverage::Uncovered(
621            "which valuetype arrives is a run-time question; the CORBA arc owns it",
622        ),
623        (C::AnnotationType, L::Nim) => Coverage::Uncovered("an annotation declares no data"),
624
625        // -- Swift -------------------------------------------------------
626        //
627        // A module flattens with `_` rather than nesting in a caseless `enum`:
628        // measured, an unqualified name inside a nested type resolves to the
629        // nested one and compiles with no diagnostic, so two IDL scopes each
630        // declaring one name would silently take the wrong type.
631        (C::Module, L::Swift) => Coverage::Rule("module-to-prefix"),
632        (C::Structure, L::Swift) => Coverage::Rule("struct-to-struct"),
633        (C::Enumeration, L::Swift) => Coverage::Rule("enum-to-enum"),
634        (C::Alias, L::Swift) => Coverage::Rule("alias-to-typealias"),
635        (C::Union, L::Swift) => Coverage::Rule("union-to-struct"),
636        (C::Bitmask, L::Swift) => Coverage::Rule("bitmask-to-optionset"),
637        (C::Bitset, L::Swift) => Coverage::Rule("bitset-to-struct"),
638        (C::Valuetype, L::Swift) => Coverage::Rule("valuetype-to-struct"),
639        (C::Const, L::Swift) => Coverage::Rule("const-to-let"),
640        (C::Exception, L::Swift) => Coverage::Rule("exception-to-struct"),
641        (C::Native, L::Swift) => Coverage::Rule("native-to-typealias"),
642        (C::Interface, L::Swift) => Coverage::Rule("interface-to-protocol"),
643        // The seven that are not declarations of their own: each becomes
644        // a type at the point of use, which is the member rule's doing.
645        (
646            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
647            L::Swift,
648        ) => Coverage::Rule("member-to-property"),
649        (C::ObjectRef, L::Swift) => Coverage::Uncovered("object references belong to the RPC arc"),
650        (C::Any, L::Swift) => Coverage::Uncovered(
651            "`any` carries its type at run time; this language has a type that would \
652             hold it and no wire form behind it",
653        ),
654        (C::ValueBase, L::Swift) => Coverage::Uncovered(
655            "which valuetype arrives is a run-time question; the CORBA arc owns it",
656        ),
657        (C::AnnotationType, L::Swift) => Coverage::Uncovered("an annotation declares no data"),
658
659        // -- Zig ---------------------------------------------------------
660        //
661        // A module flattens with `_`: a Zig file is a struct and has no
662        // namespace a declaration can be reopened in.
663        (C::Module, L::Zig) => Coverage::Rule("module-to-prefix"),
664        (C::Structure, L::Zig) => Coverage::Rule("struct-to-struct"),
665        (C::Enumeration, L::Zig) => Coverage::Rule("enum-to-enum"),
666        (C::Alias, L::Zig) => Coverage::Rule("alias-to-const"),
667        (C::Union, L::Zig) => Coverage::Rule("union-to-struct"),
668        (C::Bitmask, L::Zig) => Coverage::Rule("bitmask-to-int"),
669        (C::Bitset, L::Zig) => Coverage::Rule("bitset-to-struct"),
670        (C::Valuetype, L::Zig) => Coverage::Rule("valuetype-to-struct"),
671        (C::Const, L::Zig) => Coverage::Rule("const-to-const"),
672        (C::Exception, L::Zig) => Coverage::Rule("exception-to-struct"),
673        (C::Native, L::Zig) => Coverage::Rule("native-to-opaque"),
674        (C::Interface, L::Zig) => Coverage::Rule("interface-to-struct"),
675        // The seven that are not declarations of their own: each becomes
676        // a type at the point of use, which is the member rule's doing.
677        (
678            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
679            L::Zig,
680        ) => Coverage::Rule("member-to-field"),
681        (C::ObjectRef, L::Zig) => Coverage::Uncovered("object references belong to the RPC arc"),
682        (C::Any, L::Zig) => {
683            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
684        }
685        (C::ValueBase, L::Zig) => Coverage::Uncovered(
686            "which valuetype arrives is a run-time question; the CORBA arc owns it",
687        ),
688        (C::AnnotationType, L::Zig) => Coverage::Uncovered("an annotation declares no data"),
689
690        // -- Node (plain JavaScript) ---------------------------------------
691        //
692        // This column's materialiser (`crates/lang-rules/src/adapter/node.rs`)
693        // declares almost nothing: a struct, a union, a bitset and a
694        // valuetype are all plain object literals wherever the codec walk
695        // or the Table 9 defaulter builds one, needing no named
696        // declaration at all — "the runtime carries the shape" is the
697        // adapter's own words for it. What is covered below is a
698        // construct whose *value* is correctly represented wherever it is
699        // built; what is uncovered is a construct nothing here ever needs
700        // to name, because it is never a struct member's type in any
701        // corpus case and a dynamically-typed column has no consumer that
702        // would look one up by a declared name if it were.
703        //
704        // Three seams `crates/lang-rules/src/emit/node.rs` need no
705        // override for, because plain JavaScript's own semantics already
706        // answer what a typed sibling has to spell out. `bool_less` is
707        // the language's own `<`: it coerces `false` and `true` to 0 and
708        // 1 correctly, where TypeScript's compiler refuses the
709        // comparison outright (`crates/lang-rules/src/emit/typescript.rs`'s
710        // `bool_less` exists only for that refusal). A property name is
711        // never escaped, because IDL 4.2 §7.2.3's identifier grammar is a
712        // strict subset of ECMA-262 §12.6.1's `IdentifierName`, which has
713        // admitted every reserved word as a property key since
714        // ECMAScript 5 — `zerodds_lang_cst::node::escape_member` is the
715        // identity, always. And `@external` needs no indirection at all,
716        // because every object this column builds is already a
717        // reference: none of the `external_*` seams are overridden, the
718        // same as TypeScript's.
719        (C::Module, L::Node) => Coverage::Rule("module-to-flattened-name"),
720        (C::Structure, L::Node) => Coverage::Rule("struct-to-object-literal"),
721        (C::Union, L::Node) => Coverage::Rule("union-to-object-literal"),
722        (C::Enumeration, L::Node) => Coverage::Rule("enum-to-frozen-object"),
723        (C::Bitmask, L::Node) => Coverage::Rule("bit-to-const"),
724        (C::Bitset, L::Node) => Coverage::Rule("bitset-to-object-literal"),
725        // §7.4.1.4.3: an alias "does not define a new type", and this is
726        // the one column where that is not merely the clause but the
727        // whole of the mapping — a typedef'd member takes its resolved
728        // target's representation directly, with no declaration standing
729        // between them for a name to escape onto.
730        (C::Alias, L::Node) => Coverage::Rule("alias-transparent"),
731        (C::Valuetype, L::Node) => Coverage::Rule("valuetype-to-object-literal"),
732        (C::Const, L::Node) => Coverage::Rule("const-to-const"),
733        // The seven that are not declarations of their own: each is
734        // written where the member is, as a `number`, a `bigint`, a
735        // one-character `string`, an `Array` or a plain object property
736        // — `crates/lang-rules/src/emit/node.rs`'s module documentation
737        // carries the boundary.
738        (
739            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
740            L::Node,
741        ) => Coverage::Rule("member-to-property"),
742        (C::Native, L::Node) => Coverage::Uncovered(
743            "opaque and never a member's type in the corpus; a dynamically-typed \
744             column has no consumer that would look one up by a declared name",
745        ),
746        (C::Exception, L::Node) => Coverage::Uncovered(
747            "an exception is never a struct member's type, only an operation's \
748             raises clause; nothing here declares a name for one",
749        ),
750        (C::Interface, L::Node) => Coverage::Uncovered(
751            "an interface is the RPC arc's and not the wire's, and nothing here \
752             declares a name for one",
753        ),
754        (C::ObjectRef, L::Node) => Coverage::Uncovered("object references belong to the RPC arc"),
755        (C::Any, L::Node) => {
756            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
757        }
758        (C::ValueBase, L::Node) => Coverage::Uncovered(
759            "which valuetype arrives is a run-time question; the CORBA arc owns it",
760        ),
761        (C::AnnotationType, L::Node) => Coverage::Uncovered("an annotation declares no data"),
762
763        // -- Ada 83 --------------------------------------------------------
764        //
765        // A module flattens exactly as `adapter::ada`'s does, for the
766        // same reason: GNAT ties a compilation unit to a file name.
767        // Unlike `adapter::ada`, an interface has no rule at all here —
768        // RM83 has no interface type, no tagged type and no `abstract`,
769        // and `ada83_items` refuses one by name before any per-construct
770        // rule of the catalogue would be consulted for it, so no ghost
771        // kind is declared for one (see `rule::ada83`'s module
772        // documentation). An enumerator is `enum-to-constants`, not
773        // `enum-to-type`: RM83 has no confirmed `'Enum_Rep`/`'Enum_Val`
774        // under `-gnat83`, so an enumerator is a named `Long_Integer`
775        // constant, the same shape a bitmask's bits already have.
776        (C::Module, L::Ada83) => Coverage::Rule("module-to-prefix"),
777        (C::Structure, L::Ada83) => Coverage::Rule("struct-to-record"),
778        (C::Enumeration, L::Ada83) => Coverage::Rule("enum-to-constants"),
779        (C::Alias, L::Ada83) => Coverage::Rule("alias-to-subtype"),
780        (C::Union, L::Ada83) => Coverage::Rule("union-to-record"),
781        (C::Bitmask, L::Ada83) => Coverage::Rule("bitmask-to-type"),
782        (C::Bitset, L::Ada83) => Coverage::Rule("bitset-to-record"),
783        (C::Valuetype, L::Ada83) => Coverage::Rule("valuetype-to-record"),
784        (C::Const, L::Ada83) => Coverage::Rule("const-to-constant"),
785        (C::Exception, L::Ada83) => Coverage::Rule("exception-to-record"),
786        (C::Native, L::Ada83) => Coverage::Rule("native-to-type"),
787        // The seven that are not declarations of their own: each becomes
788        // a type at the point of use, which is the member rule's doing,
789        // exactly as in `adapter::ada`.
790        (
791            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
792            L::Ada83,
793        ) => Coverage::Rule("member-to-component"),
794        (C::Interface, L::Ada83) => Coverage::Uncovered(
795            "RM83 has no interface type, no tagged type and no `abstract` primitive \
796             operation — all three are Ada 95 or Ada 2005 additions — so `ada83_items` \
797             refuses one by name before any rule of this catalogue is consulted",
798        ),
799        (C::ObjectRef, L::Ada83) => Coverage::Uncovered("object references belong to the RPC arc"),
800        (C::Any, L::Ada83) => {
801            Coverage::Uncovered("`any` carries its type at run time; the CORBA arc owns it")
802        }
803        (C::ValueBase, L::Ada83) => Coverage::Uncovered(
804            "which valuetype arrives is a run-time question; the CORBA arc owns it",
805        ),
806        (C::AnnotationType, L::Ada83) => Coverage::Uncovered("an annotation declares no data"),
807
808        // -- F# --------------------------------------------------------
809        //
810        // The same shape `rule::fsharp`'s module documentation gives
811        // beside `rule::zig`'s: a module flattens onto the name, a
812        // union is a class with a discriminator rather than F#'s own
813        // discriminated union (`zerodds_lang_cst::fsharp`'s module
814        // documentation carries why), and a bitmask still needs
815        // file-scope constants beside its type abbreviation.
816        (C::Module, L::FSharp) => Coverage::Rule("module-to-prefix"),
817        (C::Structure, L::FSharp) => Coverage::Rule("struct-to-class"),
818        (C::Enumeration, L::FSharp) => Coverage::Rule("enum-to-enum"),
819        (C::Alias, L::FSharp) => Coverage::Rule("alias-to-abbreviation"),
820        (C::Union, L::FSharp) => Coverage::Rule("union-to-class"),
821        (C::Bitmask, L::FSharp) => Coverage::Rule("bitmask-to-int"),
822        (C::Bitset, L::FSharp) => Coverage::Rule("bitset-to-class"),
823        (C::Valuetype, L::FSharp) => Coverage::Rule("valuetype-to-class"),
824        (C::Const, L::FSharp) => Coverage::Rule("const-to-const"),
825        (C::Exception, L::FSharp) => Coverage::Rule("exception-to-class"),
826        (C::Interface, L::FSharp) => Coverage::Rule("interface-to-class"),
827        (C::Native, L::FSharp) => Coverage::Rule("native-to-opaque"),
828        // The seven that are not declarations of their own: each becomes
829        // a type at the point of use, which is `member-to-field`'s
830        // doing, as in C#.
831        (
832            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
833            L::FSharp,
834        ) => Coverage::Rule("member-to-field"),
835        (C::Any, L::FSharp) => Coverage::Uncovered(
836            "an `any` needs the dynamic type system, which is the reflective arc",
837        ),
838        (C::ValueBase, L::FSharp) => {
839            Coverage::Uncovered("no F# form; a valuetype base is not a declaration of its own")
840        }
841        (C::ObjectRef, L::FSharp) => Coverage::Uncovered("object references belong to the RPC arc"),
842        (C::AnnotationType, L::FSharp) => Coverage::Uncovered("an annotation declares no data"),
843
844        // -- Kotlin ----------------------------------------------------
845        //
846        // Kotlin shares the JVM's value model with Java, but Java's own
847        // columns above are still "not yet written" placeholders — this
848        // column was built fresh (`docs/language-columns-status.md`).
849        // An enumeration is `enum-to-object`, not an `enum class`:
850        // Kotlin's `enum class` fixes a constant to its declaration
851        // ordinal, which cannot reproduce the out-of-order or gapped
852        // `@value` DDS-XTypes 1.3 §7.4.3.5.3 admits, so an enumeration
853        // is an `object` of `const val Int` instead — the same argument
854        // `adapter::java` gives for `public static final int`. A
855        // bitmask is `bitmask-to-alias` in name only: a Kotlin
856        // `typealias` is transparent to the compiler, so the rule's
857        // declaration is the bits' constants and the holder type is
858        // used directly, with no aggregate of its own.
859        (C::Module, L::Kotlin) => Coverage::Rule("module-to-prefix"),
860        (C::Structure, L::Kotlin) => Coverage::Rule("struct-to-class"),
861        (C::Enumeration, L::Kotlin) => Coverage::Rule("enum-to-object"),
862        (C::Alias, L::Kotlin) => Coverage::Rule("alias-to-alias"),
863        (C::Union, L::Kotlin) => Coverage::Rule("union-to-class"),
864        (C::Bitmask, L::Kotlin) => Coverage::Rule("bitmask-to-alias"),
865        (C::Bitset, L::Kotlin) => Coverage::Rule("bitset-to-class"),
866        (C::Valuetype, L::Kotlin) => Coverage::Rule("valuetype-to-class"),
867        (C::Const, L::Kotlin) => Coverage::Rule("const-to-const"),
868        (C::Exception, L::Kotlin) => Coverage::Rule("exception-to-class"),
869        (C::Interface, L::Kotlin) => Coverage::Rule("interface-to-class"),
870        (C::Native, L::Kotlin) => Coverage::Rule("native-to-alias"),
871        // The seven that are not declarations of their own: each becomes
872        // a type at the point of use, which is `member-to-property`'s
873        // doing.
874        (
875            C::Primitive | C::Sequence | C::Array | C::StringType | C::Map | C::Fixed | C::ValueBox,
876            L::Kotlin,
877        ) => Coverage::Rule("member-to-property"),
878        (C::Any, L::Kotlin) => Coverage::Uncovered(
879            "an `any` needs the dynamic type system, which is the reflective arc",
880        ),
881        (C::ValueBase, L::Kotlin) => {
882            Coverage::Uncovered("no Kotlin form; a valuetype base is not a declaration of its own")
883        }
884        (C::ObjectRef, L::Kotlin) => Coverage::Uncovered("object references belong to the RPC arc"),
885        (C::AnnotationType, L::Kotlin) => Coverage::Uncovered("an annotation declares no data"),
886    }
887}
888
889/// How many cells of the table a rule covers.
890#[must_use]
891pub fn covered_count() -> usize {
892    let mut count = 0;
893    for construct in ConstructKind::ALL {
894        for language in Language::ALL {
895            if coverage_of(construct, language).is_covered() {
896                count += 1;
897            }
898        }
899    }
900    count
901}
902
903/// How many cells the table has.
904#[must_use]
905pub const fn cell_count() -> usize {
906    ConstructKind::ALL.len() * Language::ALL.len()
907}