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