facet_core/types/ty/mod.rs
1use core::fmt;
2
3use super::*;
4
5mod field;
6pub use field::*;
7
8mod proxy;
9pub use proxy::*;
10
11mod opaque_adapter;
12pub use opaque_adapter::*;
13
14mod struct_;
15pub use struct_::*;
16
17mod enum_;
18pub use enum_::*;
19
20mod union_;
21pub use union_::*;
22
23mod primitive;
24pub use primitive::*;
25
26mod sequence;
27pub use sequence::*;
28
29mod user;
30pub use user::*;
31
32mod pointer;
33pub use pointer::*;
34
35/// The definition of a shape in accordance to rust reference:
36///
37/// See <https://doc.rust-lang.org/reference/types.html>
38#[derive(Clone, Copy, Debug)]
39#[repr(C)]
40pub enum Type {
41 /// Undefined type - used as default in ShapeBuilder.
42 Undefined,
43 /// Built-in primitive.
44 Primitive(PrimitiveType),
45 /// Sequence (array, slice).
46 Sequence(SequenceType),
47 /// User-defined type (struct, enum, union).
48 User(UserType),
49 /// Pointer type (reference, raw, function pointer).
50 Pointer(PointerType),
51}
52
53impl Type {
54 /// Returns the kind of this type as a string, for use in `DeclId` computation.
55 ///
56 /// This is used when auto-computing `DeclId` for foreign generic types.
57 #[inline]
58 pub const fn kind_str(&self) -> &'static str {
59 match self {
60 Type::Undefined => "undefined",
61 Type::Primitive(_) => "primitive",
62 Type::Sequence(s) => match s {
63 SequenceType::Array(_) => "array",
64 SequenceType::Slice(_) => "slice",
65 },
66 Type::User(u) => match u {
67 UserType::Struct(_) => "struct",
68 UserType::Enum(_) => "enum",
69 UserType::Union(_) => "union",
70 UserType::Opaque => "opaque",
71 },
72 Type::Pointer(p) => match p {
73 PointerType::Reference(_) => "ref",
74 PointerType::Raw(_) => "ptr",
75 PointerType::Function(_) => "fn",
76 },
77 }
78 }
79
80 /// Create a builder for a struct type.
81 ///
82 /// # Example
83 /// ```ignore
84 /// let ty = Type::struct_builder(StructKind::Struct, &FIELDS)
85 /// .repr(Repr::c())
86 /// .build();
87 /// ```
88 #[inline]
89 pub const fn struct_builder(kind: StructKind, fields: &'static [Field]) -> TypeStructBuilder {
90 TypeStructBuilder(StructTypeBuilder::new(kind, fields))
91 }
92
93 /// Create a builder for an enum type.
94 ///
95 /// # Example
96 /// ```ignore
97 /// let ty = Type::enum_builder(EnumRepr::U8, &VARIANTS)
98 /// .repr(Repr::c())
99 /// .build();
100 /// ```
101 #[inline]
102 pub const fn enum_builder(
103 enum_repr: EnumRepr,
104 variants: &'static [Variant],
105 ) -> TypeEnumBuilder {
106 TypeEnumBuilder(EnumTypeBuilder::new(enum_repr, variants))
107 }
108
109 /// Create a builder for a union type.
110 ///
111 /// # Example
112 /// ```ignore
113 /// let ty = Type::union_builder(&FIELDS)
114 /// .repr(Repr::c())
115 /// .build();
116 /// ```
117 #[inline]
118 pub const fn union_builder(fields: &'static [Field]) -> TypeUnionBuilder {
119 TypeUnionBuilder(UnionTypeBuilder::new(fields))
120 }
121}
122
123/// Builder that produces `Type::User(UserType::Struct(...))`.
124#[derive(Clone, Copy, Debug)]
125pub struct TypeStructBuilder(StructTypeBuilder);
126
127impl TypeStructBuilder {
128 /// Set the representation for the struct type.
129 #[inline]
130 pub const fn repr(self, repr: Repr) -> Self {
131 Self(self.0.repr(repr))
132 }
133
134 /// Build the final `Type`.
135 #[inline]
136 pub const fn build(self) -> Type {
137 Type::User(UserType::Struct(self.0.build()))
138 }
139}
140
141/// Builder that produces `Type::User(UserType::Enum(...))`.
142#[derive(Clone, Copy, Debug)]
143pub struct TypeEnumBuilder(EnumTypeBuilder);
144
145impl TypeEnumBuilder {
146 /// Set the representation for the enum type.
147 #[inline]
148 pub const fn repr(self, repr: Repr) -> Self {
149 Self(self.0.repr(repr))
150 }
151
152 /// Build the final `Type`.
153 #[inline]
154 pub const fn build(self) -> Type {
155 Type::User(UserType::Enum(self.0.build()))
156 }
157}
158
159/// Builder that produces `Type::User(UserType::Union(...))`.
160#[derive(Clone, Copy, Debug)]
161pub struct TypeUnionBuilder(UnionTypeBuilder);
162
163impl TypeUnionBuilder {
164 /// Set the representation for the union type.
165 #[inline]
166 pub const fn repr(self, repr: Repr) -> Self {
167 Self(self.0.repr(repr))
168 }
169
170 /// Build the final `Type`.
171 #[inline]
172 pub const fn build(self) -> Type {
173 Type::User(UserType::Union(self.0.build()))
174 }
175}
176
177// This implementation of `Display` is user-facing output, where the users are developers.
178// It is intended to show structure up to a certain depth, but for readability and brevity,
179// some complicated types have custom formatting surrounded by guillemet characters
180// (`«` and `»`) to indicate divergence from AST.
181impl fmt::Display for Type {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 match self {
184 Type::Undefined => {
185 write!(f, "Undefined")?;
186 }
187 Type::Primitive(_) => {
188 // Defer to `Debug`, which correctly produces the intended formatting.
189 write!(f, "{self:?}")?;
190 }
191 Type::Sequence(SequenceType::Array(ArrayType { t, n })) => {
192 write!(f, "Sequence(Array(«[{t}; {n}]»))")?;
193 }
194 Type::Sequence(SequenceType::Slice(SliceType { t })) => {
195 write!(f, "Sequence(Slice(«&[{t}]»))")?;
196 }
197 Type::User(UserType::Struct(struct_type)) => {
198 struct __Display<'a>(&'a StructType);
199 impl fmt::Display for __Display<'_> {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 write!(f, "«")?;
202 write!(f, "kind: {:?}", self.0.kind)?;
203 // Field count for `TupleStruct` and `Tuple`, and field names for `Struct`.
204 // For `Unit`, we don't show anything.
205 if let StructKind::Struct = self.0.kind {
206 write!(f, ", fields: (")?;
207 let mut fields_iter = self.0.fields.iter();
208 if let Some(field) = fields_iter.next() {
209 write!(f, "{}", field.name)?;
210 for field in fields_iter {
211 write!(f, ", {}", field.name)?;
212 }
213 }
214 write!(f, ")")?;
215 } else if let StructKind::TupleStruct | StructKind::Tuple = self.0.kind {
216 write!(f, ", fields: {}", self.0.fields.len())?;
217 }
218 // Only show the `#[repr(_)]` if it's not `Rust` (unless it's `repr(packed)`).
219 if let BaseRepr::C = self.0.repr.base {
220 if self.0.repr.packed {
221 // If there are multiple `repr` hints, display as a parenthesized list.
222 write!(f, ", repr: (C, packed)")?;
223 } else {
224 write!(f, ", repr: C")?;
225 }
226 } else if let BaseRepr::Transparent = self.0.repr.base {
227 write!(f, ", repr: transparent")?;
228 // Verbatim compiler error:
229 assert!(
230 !self.0.repr.packed,
231 "transparent struct cannot have other repr hints"
232 );
233 } else if self.0.repr.packed {
234 // This is potentially meaningless, but we'll show it anyway.
235 // In this circumstance, you can assume it's `repr(Rust)`.
236 write!(f, ", repr: packed")?;
237 }
238 write!(f, "»")
239 }
240 }
241 let show_struct = __Display(struct_type);
242 write!(f, "User(Struct({show_struct}))")?;
243 }
244 Type::User(UserType::Enum(enum_type)) => {
245 struct __Display<'a>(&'a EnumType);
246 impl<'a> fmt::Display for __Display<'a> {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 write!(f, "«")?;
249 write!(f, "variants: (")?;
250 let mut variants_iter = self.0.variants.iter();
251 if let Some(variant) = variants_iter.next() {
252 write!(f, "{}", variant.name)?;
253 for variant in variants_iter {
254 write!(f, ", {}", variant.name)?;
255 }
256 }
257 write!(f, ")")?;
258 // Only show the `#[repr(_)]` if it's not `Rust`.
259 if let BaseRepr::C = self.0.repr.base {
260 // TODO: `EnumRepr` should probably be optional, and contain the fields of `Repr`.
261 // I think it is wrong to have both `Repr` and `EnumRepr` in the same type,
262 // since that allows constructing impossible states.
263 let repr_ty = match self.0.enum_repr {
264 EnumRepr::Rust => unreachable!(
265 "default Rust repr is not valid for `repr(C)` enums"
266 ),
267 EnumRepr::RustNPO => unreachable!(
268 "null-pointer optimization is only valid for `repr(Rust)`"
269 ),
270 EnumRepr::U8 => "u8",
271 EnumRepr::U16 => "u16",
272 EnumRepr::U32 => "u32",
273 EnumRepr::U64 => "u64",
274 EnumRepr::USize => "usize",
275 EnumRepr::I8 => "i8",
276 EnumRepr::I16 => "i16",
277 EnumRepr::I32 => "i32",
278 EnumRepr::I64 => "i64",
279 EnumRepr::ISize => "isize",
280 };
281 // If there are multiple `repr` hints, display as a parenthesized list.
282 write!(f, ", repr: (C, {repr_ty})")?;
283 } else if let BaseRepr::Transparent = self.0.repr.base {
284 // Extra variant hints are not supported for `repr(transparent)`.
285 write!(f, ", repr: transparent")?;
286 }
287 // Verbatim compiler error:
288 assert!(
289 !self.0.repr.packed,
290 "attribute should be applied to a struct or union"
291 );
292 write!(f, "»")
293 }
294 }
295 let show_enum = __Display(enum_type);
296 write!(f, "User(Enum({show_enum}))")?;
297 }
298 Type::User(UserType::Union(union_type)) => {
299 struct __Display<'a>(&'a UnionType);
300 impl<'a> fmt::Display for __Display<'a> {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 write!(f, "«")?;
303 write!(f, "fields: (")?;
304 let mut fields_iter = self.0.fields.iter();
305 if let Some(field) = fields_iter.next() {
306 write!(f, "{}", field.name)?;
307 for field in fields_iter {
308 write!(f, ", {}", field.name)?;
309 }
310 }
311 write!(f, ")")?;
312 // Only show the `#[repr(_)]` if it's not `Rust` (unless it's `repr(packed)`).
313 if let BaseRepr::C = self.0.repr.base {
314 if self.0.repr.packed {
315 // If there are multiple `repr` hints, display as a parenthesized list.
316 write!(f, ", repr: (C, packed)")?;
317 } else {
318 write!(f, ", repr: C")?;
319 }
320 } else if let BaseRepr::Transparent = self.0.repr.base {
321 // Nothing needs to change if `transparent_unions` is stabilized.
322 // <https://github.com/rust-lang/rust/issues/60405>
323 write!(f, ", repr: transparent")?;
324 // Verbatim compiler error:
325 assert!(
326 !self.0.repr.packed,
327 "transparent union cannot have other repr hints"
328 );
329 } else if self.0.repr.packed {
330 // Here `Rust` is displayed because a lint asks you to specify explicitly,
331 // despite the fact that `repr(Rust)` is the default.
332 write!(f, ", repr: (Rust, packed)")?;
333 }
334 write!(f, "»")?;
335 Ok(())
336 }
337 }
338 let show_union = __Display(union_type);
339 write!(f, "User(Union({show_union}))")?;
340 }
341 Type::User(UserType::Opaque) => {
342 write!(f, "User(Opaque)")?;
343 }
344 Type::Pointer(PointerType::Reference(ptr_type)) => {
345 let show_ref = if ptr_type.mutable { "&mut " } else { "&" };
346 let target = ptr_type.target();
347 write!(f, "Pointer(Reference(«{show_ref}{target}»))")?;
348 }
349 Type::Pointer(PointerType::Raw(ptr_type)) => {
350 let show_raw = if ptr_type.mutable { "*mut " } else { "*const " };
351 let target = ptr_type.target();
352 write!(f, "Pointer(Raw(«{show_raw}{target}»))")?;
353 }
354 Type::Pointer(PointerType::Function(fn_ptr_def)) => {
355 struct __Display<'a>(&'a FunctionPointerDef);
356 impl fmt::Display for __Display<'_> {
357 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358 write!(f, "«")?;
359 write!(f, "fn(")?;
360 let mut args_iter = self.0.parameters.iter();
361 if let Some(arg) = args_iter.next() {
362 write!(f, "{arg}")?;
363 for arg in args_iter {
364 write!(f, ", {arg}")?;
365 }
366 }
367 let ret_ty = self.0.return_type;
368 write!(f, ") -> {ret_ty}")?;
369 write!(f, "»")?;
370 Ok(())
371 }
372 }
373 let show_fn = __Display(fn_ptr_def);
374 write!(f, "Pointer(Function({show_fn}))")?;
375 }
376 }
377 Ok(())
378 }
379}