Skip to main content

rucc_types/
types.rs

1//! The type table: interning, canonicalisation, and the nominal declarations.
2//!
3//! Design: `spec/07-types-and-semantics.md` section 7.1.
4//!
5//! There is one [`Types`] per translation unit and every [`TypeId`] belongs to it. Interning
6//! is what makes type identity an integer comparison, which is the single most frequent
7//! question the compiler asks, and it is also what makes the canonical form free to look up:
8//! each entry stores the id of its own canonical type, so stripping a stack of typedefs is one
9//! array read rather than a walk.
10
11use std::collections::HashMap;
12use std::num::NonZeroU32;
13
14use rucc_base::{Idx, Symbol};
15
16use crate::kind::{
17    ArrayLen, EnumId, FloatKind, FunctionId, FunctionType, IntKind, Qualifiers, RecordId,
18    RecordKind, Type, TypeKind,
19};
20use crate::layout::Layout;
21use crate::record::{Field, RecordLayout, VariableLayout};
22
23/// The identity of a type.
24///
25/// Four bytes, `Copy`, and equal exactly when the two types are the same type. Ids from two
26/// different [`Types`] tables are not comparable, which is not a restriction in practice
27/// because there is one table per translation unit.
28#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
29pub struct TypeId(Idx<Entry>);
30
31impl std::fmt::Debug for TypeId {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        write!(f, "TypeId#{}", self.0.raw())
34    }
35}
36
37/// One row of the table.
38///
39/// The canonical id is stored rather than computed because almost every read of a type wants
40/// it, and computing it means walking a chain whose length is however many typedefs the header
41/// author felt like writing.
42#[derive(Debug, Clone, Copy)]
43struct Entry {
44    ty: Type,
45    canonical: TypeId,
46}
47
48/// What is known about one `struct` or `union` declaration.
49#[derive(Debug, Clone)]
50pub struct RecordInfo {
51    /// Whether it is a `struct` or a `union`.
52    pub kind: RecordKind,
53    /// The tag, absent for an anonymous one.
54    pub tag: Option<Symbol>,
55    /// The layout, absent until the members have been seen and laid out.
56    ///
57    /// This is also what says whether the type is complete. A record is incomplete from the
58    /// point its tag is first mentioned until its closing brace, and code in between may
59    /// declare pointers to it and nothing else.
60    ///
61    /// For a record with a member of no fixed size the alignment here is the right one and the
62    /// size is zero, since an alignment never depends on a length. [`RecordInfo::variable`] is
63    /// what holds the size in that case and what says the size here means nothing.
64    pub layout: Option<Layout>,
65    /// How long the record is and where its members sit, where those are not numbers.
66    ///
67    /// Present on exactly the records C calls variably modified, meaning a variable length array
68    /// is somewhere among the members, which may only be written inside a function.
69    pub variable: Option<VariableLayout>,
70    /// The members, placed, and empty until the record is complete.
71    ///
72    /// One entry per member the program wrote, in that order, so a caller that kept the
73    /// declarations can index the two together.
74    pub fields: Vec<Field>,
75    /// Whether `__attribute__((transparent_union))` was written on it and held up.
76    ///
77    /// Only ever true of a union, and only of one whose first member is the size and the
78    /// alignment of the whole of it, which is what makes passing the union and passing that
79    /// member the same thing at a call. What it buys is two rules: a parameter of this type is
80    /// compatible with a parameter of any member's type, and a value assigned to it is put into
81    /// whichever member it fits. Both are in `spec/13-gnu-compat.md`.
82    pub transparent: bool,
83    /// Whether the scalars in it are stored in the byte order the target does not have.
84    ///
85    /// What `__attribute__((scalar_storage_order("big-endian")))` on a little-endian target asks
86    /// for, and what the same attribute written with the target's own order does not. It changes
87    /// nothing about where the members sit: the record is the size and the alignment it would
88    /// otherwise be and every member is at the offset it would otherwise be at. What it changes
89    /// is the order of the bytes inside each scalar, which is a byte swap on every load and
90    /// store, and the end of a storage unit a bit-field is allocated from. Both are in
91    /// `spec/13-gnu-compat.md`.
92    pub reverse: bool,
93}
94
95/// What is known about one `enum` declaration.
96#[derive(Debug, Clone)]
97pub struct EnumInfo {
98    /// The tag, absent for an anonymous one.
99    pub tag: Option<Symbol>,
100    /// The type the enumerators are represented in, absent until it is decided.
101    ///
102    /// C23 lets the program write it, and before that it is chosen once every enumerator has
103    /// been seen. Either way it is a fact about the declaration rather than about the type
104    /// system, so it is recorded here and not derived twice.
105    pub underlying: Option<TypeId>,
106    /// Whether the underlying type was written by the program rather than chosen.
107    ///
108    /// It changes the answer to what an enumerator's own type is, and it decides whether an
109    /// enumerator that does not fit is an error or a reason to widen.
110    pub fixed: bool,
111    /// The enumerators in the order the program wrote them, empty until the enumeration is
112    /// complete.
113    ///
114    /// Nothing the type system itself asks about, since an enumerator is a name in a scope and
115    /// what has the type is the enumeration rather than the list. It is here because the
116    /// declaration is the only place the list ever exists, the scope it is declared into throws
117    /// away the order and the tie to the enumeration, and a reader that wants the list later has
118    /// nowhere else to ask. Debug information is that reader: without this a debugger prints the
119    /// number where the program wrote the name.
120    pub enumerators: Vec<Enumerator>,
121}
122
123/// One enumerator of an enumeration.
124#[derive(Debug, Clone)]
125pub struct Enumerator {
126    /// The name the program wrote.
127    pub name: Symbol,
128    /// Its value, in the enumeration's underlying type.
129    ///
130    /// Held as an [`i128`] because the value is worked out before the underlying type is chosen,
131    /// and because the widest enumeration a target has still has to fit in something wider than
132    /// itself while the list is being read.
133    pub value: i128,
134}
135
136/// A typedef name the program wrote, and what it stands for.
137#[derive(Debug, Clone, Copy)]
138pub struct Alias {
139    /// The name.
140    pub name: Symbol,
141    /// The type it was written for, which is the same type the name resolves to rather than a
142    /// type of its own.
143    pub of: TypeId,
144}
145
146/// A record member written with a typedef name, and the name it was written with.
147#[derive(Debug, Clone, Copy)]
148pub struct Spelled {
149    /// The record the member is in.
150    pub record: RecordId,
151    /// The member.
152    pub member: Symbol,
153    /// The typedef name its specifiers named.
154    pub name: Symbol,
155    /// The type the name stood for, which the member's type is built on top of.
156    pub of: TypeId,
157}
158
159/// Every type in one translation unit.
160#[derive(Debug)]
161pub struct Types {
162    entries: Vec<Entry>,
163    map: HashMap<Type, TypeId>,
164    functions: Vec<FunctionType>,
165    function_map: HashMap<FunctionType, FunctionId>,
166    records: Vec<RecordInfo>,
167    enums: Vec<EnumInfo>,
168    aliases: Vec<Alias>,
169    spelled: Vec<Spelled>,
170    void: TypeId,
171    boolean: TypeId,
172    ints: [TypeId; 13],
173    floats: [TypeId; 9],
174}
175
176impl Default for Types {
177    fn default() -> Types {
178        Types::new()
179    }
180}
181
182impl Types {
183    /// A table holding the basic types and nothing else.
184    ///
185    /// The basic types are interned here rather than on first use so that asking for `int` is
186    /// an array read. They are the ones asked for by far the most often, because every
187    /// integer promotion produces one.
188    #[must_use]
189    pub fn new() -> Types {
190        let mut types = Types {
191            entries: Vec::new(),
192            map: HashMap::new(),
193            functions: Vec::new(),
194            function_map: HashMap::new(),
195            records: Vec::new(),
196            enums: Vec::new(),
197            aliases: Vec::new(),
198            spelled: Vec::new(),
199            // Fixed up immediately below. There is no id to put here before the table exists,
200            // and an `Option` on each of them would be paid for on every read for the sake of
201            // four lines of construction.
202            void: TypeId(Idx::new(0)),
203            boolean: TypeId(Idx::new(0)),
204            ints: [TypeId(Idx::new(0)); 13],
205            floats: [TypeId(Idx::new(0)); 9],
206        };
207        types.void = types.intern(Type::new(TypeKind::Void));
208        types.boolean = types.intern(Type::new(TypeKind::Bool));
209        for kind in IntKind::ALL {
210            types.ints[kind.index()] = types.intern(Type::new(TypeKind::Int(kind)));
211        }
212        for kind in FloatKind::ALL {
213            types.floats[kind.index()] = types.intern(Type::new(TypeKind::Float(kind)));
214        }
215        types
216    }
217
218    /// How many distinct types there are.
219    #[must_use]
220    pub fn len(&self) -> usize {
221        self.entries.len()
222    }
223
224    /// Whether the table is empty, which it never is once [`Types::new`] has run.
225    #[must_use]
226    pub fn is_empty(&self) -> bool {
227        self.entries.is_empty()
228    }
229
230    /// The type `id` stands for, with its qualifiers.
231    ///
232    /// # Panics
233    ///
234    /// Panics if `id` came from a different table.
235    #[must_use]
236    pub fn get(&self, id: TypeId) -> Type {
237        self.entries[id.0.index()].ty
238    }
239
240    /// What `id` is, ignoring its qualifiers.
241    ///
242    /// # Panics
243    ///
244    /// Panics if `id` came from a different table.
245    #[must_use]
246    pub fn kind(&self, id: TypeId) -> TypeKind {
247        self.get(id).kind
248    }
249
250    /// What `id` is qualified with.
251    ///
252    /// # Panics
253    ///
254    /// Panics if `id` came from a different table.
255    #[must_use]
256    pub fn quals(&self, id: TypeId) -> Qualifiers {
257        self.get(id).quals
258    }
259
260    /// The canonical form of `id`, with every typedef resolved at every depth.
261    ///
262    /// This is what every semantic rule reads. `id` itself is what every diagnostic prints.
263    ///
264    /// # Panics
265    ///
266    /// Panics if `id` came from a different table.
267    #[must_use]
268    pub fn canonical(&self, id: TypeId) -> TypeId {
269        self.entries[id.0.index()].canonical
270    }
271
272    /// Whether `id` is written with a typedef name somewhere inside it.
273    ///
274    /// # Panics
275    ///
276    /// Panics if `id` came from a different table.
277    #[must_use]
278    pub fn is_sugar(&self, id: TypeId) -> bool {
279        self.canonical(id) != id
280    }
281
282    /// `void`.
283    #[must_use]
284    pub fn void(&self) -> TypeId {
285        self.void
286    }
287
288    /// `bool`, which is `_Bool` in the older spellings.
289    ///
290    /// Named this way because `bool` is a Rust keyword and `r#bool` at every call site would
291    /// be a worse trade than one unusual name here.
292    #[must_use]
293    pub fn boolean(&self) -> TypeId {
294        self.boolean
295    }
296
297    /// One of the standard integer types.
298    #[must_use]
299    pub fn int(&self, kind: IntKind) -> TypeId {
300        self.ints[kind.index()]
301    }
302
303    /// One of the real floating types.
304    #[must_use]
305    pub fn float(&self, kind: FloatKind) -> TypeId {
306        self.floats[kind.index()]
307    }
308
309    /// `_Complex T` for the real type `T`, which is one of the halves.
310    pub fn complex(&mut self, part: TypeId) -> TypeId {
311        self.intern(Type::new(TypeKind::Complex(part)))
312    }
313
314    /// `_Complex T` for a real floating `T`, which is the spelling C has.
315    pub fn complex_float(&mut self, kind: FloatKind) -> TypeId {
316        let part = self.float(kind);
317        self.complex(part)
318    }
319
320    /// `_BitInt(width)`, signed or not.
321    ///
322    /// The width is not checked against the target's maximum here. That check belongs where
323    /// there is a span to point at, and building the type anyway means the rest of the
324    /// declaration still gets checked instead of collapsing into a cascade.
325    pub fn bit_int(&mut self, signed: bool, width: u32) -> TypeId {
326        self.intern(Type::new(TypeKind::BitInt { signed, width }))
327    }
328
329    /// A pointer to `pointee`.
330    pub fn pointer(&mut self, pointee: TypeId) -> TypeId {
331        self.intern(Type::new(TypeKind::Pointer(pointee)))
332    }
333
334    /// `_Atomic(inner)`.
335    pub fn atomic(&mut self, inner: TypeId) -> TypeId {
336        self.intern(Type::new(TypeKind::Atomic(inner)))
337    }
338
339    /// An array of `elem`.
340    pub fn array(&mut self, elem: TypeId, len: ArrayLen) -> TypeId {
341        self.intern(Type::new(TypeKind::Array { elem, len }))
342    }
343
344    /// A GNU vector of `len` elements of `elem`.
345    pub fn vector(&mut self, elem: TypeId, len: u32) -> TypeId {
346        self.intern(Type::new(TypeKind::Vector { elem, len }))
347    }
348
349    /// A function type, deduplicated by content.
350    ///
351    /// # Panics
352    ///
353    /// Panics past four billion distinct function types in one translation unit. The
354    /// alternative to panicking is handing back an id that means a different type, so the
355    /// limit is stated rather than worked around.
356    pub fn function(&mut self, signature: FunctionType) -> TypeId {
357        let id = match self.function_map.get(&signature) {
358            Some(&id) => id,
359            None => {
360                let id = FunctionId(u32::try_from(self.functions.len()).expect("too many types"));
361                self.functions.push(signature.clone());
362                self.function_map.insert(signature, id);
363                id
364            }
365        };
366        self.intern(Type::new(TypeKind::Function(id)))
367    }
368
369    /// The signature behind a function type.
370    ///
371    /// # Panics
372    ///
373    /// Panics if `id` came from a different table.
374    #[must_use]
375    pub fn signature(&self, id: FunctionId) -> &FunctionType {
376        &self.functions[id.0 as usize]
377    }
378
379    /// Declares a `struct` or `union` that has been named but not yet laid out.
380    ///
381    /// Each call makes a new type even for the same tag, because a record type in C is its
382    /// declaration. Redeclaring a tag in an inner scope makes a different type, and the two
383    /// being distinct is what the scope rules mean.
384    ///
385    /// # Panics
386    ///
387    /// Panics past four billion record declarations in one translation unit.
388    pub fn declare_record(&mut self, kind: RecordKind, tag: Option<Symbol>) -> RecordId {
389        let id = RecordId(u32::try_from(self.records.len()).expect("too many types"));
390        self.records.push(RecordInfo {
391            kind,
392            tag,
393            layout: None,
394            variable: None,
395            fields: Vec::new(),
396            transparent: false,
397            reverse: false,
398        });
399        id
400    }
401
402    /// Records that a union was declared transparent, which is a decision made elsewhere.
403    ///
404    /// Whether the attribute holds up is a question about the members and their layout, so it is
405    /// answered where the members are read rather than here, and this only writes the answer down.
406    /// It is a fact about the declaration and not about one spelling of it, which is why the whole
407    /// record is marked rather than a variant of the type: every name for the union is the same
408    /// union and a parameter written with any of them takes the same values.
409    ///
410    /// # Panics
411    ///
412    /// Panics if `id` came from a different table.
413    pub fn make_transparent(&mut self, id: RecordId) {
414        self.records[id.0 as usize].transparent = true;
415    }
416
417    /// Records that a record holds its scalars in the byte order the target does not have.
418    ///
419    /// Which order the attribute asked for and which one the target has are both known where the
420    /// attribute is read, so what arrives here is the answer to the one question the rest of the
421    /// compiler asks. It is a fact about the declaration rather than about one spelling of it, for
422    /// the reason [`Types::make_transparent`] gives, and it is set after the members are laid out
423    /// because it changes nothing about the layout.
424    ///
425    /// # Panics
426    ///
427    /// Panics if `id` came from a different table.
428    pub fn make_reverse_order(&mut self, id: RecordId) {
429        self.records[id.0 as usize].reverse = true;
430    }
431
432    /// The type of a declared record.
433    pub fn record(&mut self, id: RecordId) -> TypeId {
434        self.intern(Type::new(TypeKind::Record(id)))
435    }
436
437    /// What is known about a declared record.
438    ///
439    /// # Panics
440    ///
441    /// Panics if `id` came from a different table.
442    #[must_use]
443    pub fn record_info(&self, id: RecordId) -> &RecordInfo {
444        &self.records[id.0 as usize]
445    }
446
447    /// Every record declared so far, in declaration order.
448    ///
449    /// For whoever wants to say something about all of them rather than about one, which so
450    /// far is [`measure_all`](crate::measure_all), measuring how their bytes fall into granules.
451    ///
452    /// # Panics
453    ///
454    /// Panics if more than `u32::MAX` records have been declared, which every other index into
455    /// this table would already have panicked on.
456    pub fn records(&self) -> impl Iterator<Item = (RecordId, &RecordInfo)> {
457        self.records
458            .iter()
459            .enumerate()
460            .map(|(index, info)| (RecordId(u32::try_from(index).expect("a declared record")), info))
461    }
462
463    /// Completes a record by recording what [`layout_record`](crate::layout_record) produced.
464    ///
465    /// # Panics
466    ///
467    /// Panics if `id` came from a different table.
468    pub fn complete_record(&mut self, id: RecordId, laid_out: RecordLayout) {
469        let info = &mut self.records[id.0 as usize];
470        info.layout = Some(laid_out.layout);
471        info.variable = laid_out.variable;
472        info.fields = laid_out.fields;
473    }
474
475    /// The member of a record with the given name.
476    ///
477    /// Direct members only. Reaching into an anonymous member is a name lookup with a path to
478    /// build rather than a search, so it belongs to whoever is resolving the expression.
479    ///
480    /// # Panics
481    ///
482    /// Panics if `id` came from a different table.
483    #[must_use]
484    pub fn field(&self, id: RecordId, name: Symbol) -> Option<&Field> {
485        self.records[id.0 as usize].fields.iter().find(|field| field.name == Some(name))
486    }
487
488    /// Declares an `enum` whose underlying type is not decided yet.
489    ///
490    /// # Panics
491    ///
492    /// Panics past four billion enumeration declarations in one translation unit.
493    pub fn declare_enum(&mut self, tag: Option<Symbol>) -> EnumId {
494        let id = EnumId(u32::try_from(self.enums.len()).expect("too many types"));
495        self.enums.push(EnumInfo { tag, underlying: None, fixed: false, enumerators: Vec::new() });
496        id
497    }
498
499    /// The type of a declared enumeration.
500    pub fn enumeration(&mut self, id: EnumId) -> TypeId {
501        self.intern(Type::new(TypeKind::Enum(id)))
502    }
503
504    /// What is known about a declared enumeration.
505    ///
506    /// # Panics
507    ///
508    /// Panics if `id` came from a different table.
509    #[must_use]
510    pub fn enum_info(&self, id: EnumId) -> &EnumInfo {
511        &self.enums[id.0 as usize]
512    }
513
514    /// Records what an enumeration is represented in, and whether the program said so.
515    ///
516    /// # Panics
517    ///
518    /// Panics if `id` came from a different table.
519    pub fn complete_enum(&mut self, id: EnumId, underlying: TypeId, fixed: bool) {
520        let info = &mut self.enums[id.0 as usize];
521        info.underlying = Some(underlying);
522        info.fixed = fixed;
523    }
524
525    /// Records what an enumeration's enumerators are.
526    ///
527    /// Apart from [`Types::complete_enum`] because it is a different fact with a different reader.
528    /// What an enumeration is represented in decides what its values do in arithmetic and is asked
529    /// by the rest of the compiler; the list of names is asked by nothing but the debug
530    /// information, and an enumeration that reaches completion without one, which is what a C23
531    /// declaration that writes an underlying type and no body does, is complete all the same.
532    ///
533    /// # Panics
534    ///
535    /// Panics if `id` came from a different table.
536    pub fn list_enumerators(&mut self, id: EnumId, enumerators: Vec<Enumerator>) {
537        self.enums[id.0 as usize].enumerators = enumerators;
538    }
539
540    /// Records that the program wrote `name` as a typedef name for `of`.
541    ///
542    /// Beside the table rather than in it, and that is the decision this is. A typedef name is a
543    /// second name for a type and not a type of its own, so an ordinary typedef interns nothing
544    /// and the name is written nowhere the types can be asked for it. Making it a type of its own
545    /// would mean two names for one type are two ids, and then the equality of two [`TypeId`]s
546    /// stops meaning the two are the same type, which is the question this table is built to
547    /// answer in one comparison. So the names go in a list that changes nothing about what a type
548    /// is.
549    ///
550    /// What the list cannot answer is which of two names a particular declaration was written
551    /// with, since that is a fact about the declaration and this is a fact about the type. A
552    /// reader gets the names the program wrote and what each one stands for, and no more.
553    pub fn alias(&mut self, name: Symbol, of: TypeId) {
554        if self.aliases.iter().any(|had| had.name == name && had.of == of) {
555            return;
556        }
557        self.aliases.push(Alias { name, of });
558    }
559
560    /// Every typedef name the program wrote, in the order it wrote them.
561    #[must_use]
562    pub fn aliases(&self) -> &[Alias] {
563        &self.aliases
564    }
565
566    /// Records that a member of a record was written with a typedef name.
567    ///
568    /// Here rather than on the member, for the reason the aliases above are beside the table
569    /// rather than in it: which name a member was written with says nothing about the record's
570    /// layout or about which records are compatible, and the member is compared for both. The
571    /// debug information is the one reader, and it wants `size_type n` where the program wrote it.
572    pub fn record_member_spelling(&mut self, spelled: Spelled) {
573        self.spelled.push(spelled);
574    }
575
576    /// Every record member written with a typedef name, in the order they were written.
577    #[must_use]
578    pub fn member_spellings(&self) -> &[Spelled] {
579        &self.spelled
580    }
581
582    /// A typedef name standing for `underlying`.
583    pub fn typedef(&mut self, name: Symbol, underlying: TypeId) -> TypeId {
584        self.intern(Type::new(TypeKind::Typedef { name, underlying, align: None }))
585    }
586
587    /// The same, for a typedef that said what an object of it is aligned to.
588    ///
589    /// `align` is in bytes and is what the type is aligned to rather than a floor on it, which
590    /// is what `__attribute__((aligned(n)))` means in this one position. See
591    /// [`TypeKind::Typedef`].
592    pub fn aligned_typedef(
593        &mut self,
594        name: Symbol,
595        underlying: TypeId,
596        align: NonZeroU32,
597    ) -> TypeId {
598        self.intern(Type::new(TypeKind::Typedef { name, underlying, align: Some(align) }))
599    }
600
601    /// What a typedef in `id`'s sugar asked an object of it to be aligned to, and [`None`] when
602    /// none of them asked for anything.
603    ///
604    /// The nearest one wins, because `typedef L M __attribute__((aligned(8)))` over an `L` that
605    /// asked for two is an eight and not a two: the outer typedef is the one the declaration was
606    /// written with. Below the sugar there is nothing to find, since only a typedef can carry one
607    /// of these, so the walk stops at the first node that is not one.
608    ///
609    /// # Panics
610    ///
611    /// Panics if `id` came from a different table.
612    #[must_use]
613    pub fn align_override(&self, id: TypeId) -> Option<NonZeroU32> {
614        let mut id = id;
615        loop {
616            let TypeKind::Typedef { underlying, align, .. } = self.kind(id) else { return None };
617            if align.is_some() {
618                return align;
619            }
620            id = underlying;
621        }
622    }
623
624    /// `id` with `quals` added to whatever it already carries.
625    ///
626    /// Qualifying an array qualifies its element type and leaves the array itself unqualified,
627    /// which is 6.7.3p10 and is not a shortcut. An array type has no qualifiers of its own,
628    /// and if it did then `const` on an array parameter would mean nothing at all.
629    pub fn qualified(&mut self, id: TypeId, quals: Qualifiers) -> TypeId {
630        if quals.is_none() {
631            return id;
632        }
633        let ty = self.get(id);
634        if let TypeKind::Array { elem, len } = ty.kind {
635            let elem = self.qualified(elem, quals);
636            return self.intern(Type { kind: TypeKind::Array { elem, len }, quals: ty.quals });
637        }
638        self.intern(Type { kind: ty.kind, quals: ty.quals.with(quals) })
639    }
640
641    /// `id` with every qualifier removed from its outermost node.
642    ///
643    /// Only the outermost, because that is what the standard means by the unqualified version
644    /// of a type. The pointee of a `const char *` stays `const`.
645    pub fn unqualified(&mut self, id: TypeId) -> TypeId {
646        let ty = self.get(id);
647        if ty.quals.is_none() {
648            return id;
649        }
650        self.intern(Type::new(ty.kind))
651    }
652
653    /// The qualifiers an object of `id` carries, which for an array are its element's.
654    ///
655    /// [`Self::quals`] answers what the node holds, and [`Self::qualified`] has just put an array's
656    /// qualifiers on its element rather than on the array, so the node holds nothing and an object
657    /// of the type is still `const`. That gap is only visible in one place, which is a pointer to an
658    /// array: `const int (*)[4]` points at something nobody may write to and asking the array node
659    /// says otherwise.
660    #[must_use]
661    pub fn object_quals(&self, id: TypeId) -> Qualifiers {
662        let ty = self.get(id);
663        match ty.kind {
664            TypeKind::Array { elem, .. } => ty.quals.with(self.object_quals(elem)),
665            _ => ty.quals,
666        }
667    }
668
669    /// `id` with the qualifiers of an object of it removed, which for an array are its element's.
670    ///
671    /// [`Self::unqualified`] taken through an array for the same reason [`Self::object_quals`] is,
672    /// so that the two agree about where an array keeps its qualifiers. What it is for is the
673    /// comparison in a pointer assignment: C's own compatibility says `const int [4]` and `int [4]`
674    /// are different types, because the element types are, so `const int (*)[4] = p` would be an
675    /// incompatible pointer rather than a qualifier being added. Every compiler takes it, C23 says
676    /// so outright, and taking the qualifiers off both sides before comparing is what makes the
677    /// assignment rule read the array the way it reads everything else.
678    pub fn unqualified_object(&mut self, id: TypeId) -> TypeId {
679        let ty = self.get(id);
680        if let TypeKind::Array { elem, len } = ty.kind {
681            let elem = self.unqualified_object(elem);
682            return self.intern(Type::new(TypeKind::Array { elem, len }));
683        }
684        self.unqualified(id)
685    }
686
687    /// The id for `ty`, making one if this is the first time it has been asked for.
688    fn intern(&mut self, ty: Type) -> TypeId {
689        if let Some(&id) = self.map.get(&ty) {
690            return id;
691        }
692        // Canonicalising can intern other types, which means `self.entries` may have grown by
693        // the time this returns and the id below has to be taken afterwards. It cannot have
694        // interned `ty` itself, because a canonical type differs from the sugar it came from,
695        // but the second lookup is one hash of a cold path against a duplicate entry that
696        // would quietly break the promise that equal ids mean equal types.
697        let canonical = self.canonicalise(&ty);
698        if let Some(&id) = self.map.get(&ty) {
699            return id;
700        }
701        let id = TypeId(Idx::from_usize(self.entries.len()));
702        self.entries.push(Entry { ty, canonical: canonical.unwrap_or(id) });
703        self.map.insert(ty, id);
704        id
705    }
706
707    /// The canonical form of `ty`, or `None` when `ty` is already canonical.
708    ///
709    /// A typedef is not the only place sugar hides. `T *` is sugar when `T` is, and so is an
710    /// array of one, and so is a function that returns one, so this rebuilds the type around
711    /// whatever its parts canonicalise to rather than only looking at the outermost node.
712    fn canonicalise(&mut self, ty: &Type) -> Option<TypeId> {
713        match ty.kind {
714            TypeKind::Typedef { underlying, .. } => {
715                let base = self.canonical(underlying);
716                Some(self.qualified(base, ty.quals))
717            }
718            TypeKind::Pointer(inner) => self.rebuild(ty, inner, TypeKind::Pointer),
719            TypeKind::Atomic(inner) => self.rebuild(ty, inner, TypeKind::Atomic),
720            TypeKind::Complex(part) => self.rebuild(ty, part, TypeKind::Complex),
721            TypeKind::Array { elem, len } => {
722                self.rebuild(ty, elem, |elem| TypeKind::Array { elem, len })
723            }
724            TypeKind::Vector { elem, len } => {
725                self.rebuild(ty, elem, |elem| TypeKind::Vector { elem, len })
726            }
727            TypeKind::Function(id) => self.canonicalise_function(ty, id),
728            TypeKind::Void
729            | TypeKind::Bool
730            | TypeKind::Int(_)
731            | TypeKind::Float(_)
732            | TypeKind::BitInt { .. }
733            | TypeKind::Record(_)
734            | TypeKind::Enum(_) => None,
735        }
736    }
737
738    /// The canonical form of a type built out of one other type.
739    fn rebuild(
740        &mut self,
741        ty: &Type,
742        inner: TypeId,
743        make: impl FnOnce(TypeId) -> TypeKind,
744    ) -> Option<TypeId> {
745        let canonical = self.canonical(inner);
746        if canonical == inner {
747            return None;
748        }
749        Some(self.intern(Type { kind: make(canonical), quals: ty.quals }))
750    }
751
752    /// The canonical form of a function type, which is sugar when any part of its signature is.
753    fn canonicalise_function(&mut self, ty: &Type, id: FunctionId) -> Option<TypeId> {
754        let signature = self.signature(id).clone();
755        let ret = self.canonical(signature.ret);
756        let params: Vec<TypeId> =
757            signature.params.iter().map(|&param| self.canonical(param)).collect();
758        if ret == signature.ret && params == signature.params {
759            return None;
760        }
761        let canonical = FunctionType { ret, params, ..signature };
762        let id = self.function(canonical);
763        Some(self.qualified(id, ty.quals))
764    }
765}