1use std::borrow::Cow;
6
7use syn::ext::IdentExt;
8
9use crate::bindgen::config::{Config, Language};
10use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
11use crate::bindgen::dependencies::Dependencies;
12use crate::bindgen::ir::{GenericArgument, GenericParams, GenericPath, Path};
13use crate::bindgen::library::Library;
14use crate::bindgen::monomorph::Monomorphs;
15use crate::bindgen::utilities::IterHelpers;
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub enum PrimitiveType {
19 Void,
20 Bool,
21 Char,
22 SChar,
23 UChar,
24 Char32,
25 Float,
26 Double,
27 VaList,
28 PtrDiffT,
29 Integer {
30 zeroable: bool,
31 signed: bool,
32 kind: IntKind,
33 },
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
37pub enum IntKind {
38 Short,
39 Int,
40 Long,
41 LongLong,
42 SizeT,
43 Size,
44 B8,
45 B16,
46 B32,
47 B64,
48}
49
50impl PrimitiveType {
51 pub fn maybe(path: &str) -> Option<PrimitiveType> {
52 Some(match path {
53 "c_void" => PrimitiveType::Void,
54 "c_char" => PrimitiveType::Char,
55 "c_schar" => PrimitiveType::SChar,
56 "c_uchar" => PrimitiveType::UChar,
57 "c_float" => PrimitiveType::Float,
58 "c_double" => PrimitiveType::Double,
59 "ptrdiff_t" => PrimitiveType::PtrDiffT,
60 "VaList" => PrimitiveType::VaList,
61 "bool" => PrimitiveType::Bool,
62 "char" => PrimitiveType::Char32,
63
64 "f32" => PrimitiveType::Float,
65 "f64" => PrimitiveType::Double,
66
67 _ => return Self::maybe_integer(path),
68 })
69 }
70
71 fn maybe_integer(path: &str) -> Option<PrimitiveType> {
73 let (kind, signed) = match path {
74 "c_short" => (IntKind::Short, true),
75 "c_int" => (IntKind::Int, true),
76 "c_long" => (IntKind::Long, true),
77 "c_longlong" => (IntKind::LongLong, true),
78 "ssize_t" => (IntKind::SizeT, true),
79 "c_ushort" => (IntKind::Short, false),
80 "c_uint" => (IntKind::Int, false),
81 "c_ulong" => (IntKind::Long, false),
82 "c_ulonglong" => (IntKind::LongLong, false),
83 "size_t" => (IntKind::SizeT, false),
84 "RawFd" => (IntKind::Int, true),
85
86 "isize" | "intptr_t" => (IntKind::Size, true),
87 "usize" | "uintptr_t" => (IntKind::Size, false),
88
89 "u8" | "uint8_t" => (IntKind::B8, false),
90 "u16" | "uint16_t" => (IntKind::B16, false),
91 "u32" | "uint32_t" => (IntKind::B32, false),
92 "u64" | "uint64_t" => (IntKind::B64, false),
93 "i8" | "int8_t" => (IntKind::B8, true),
94 "i16" | "int16_t" => (IntKind::B16, true),
95 "i32" | "int32_t" => (IntKind::B32, true),
96 "i64" | "int64_t" => (IntKind::B64, true),
97
98 _ => return Self::maybe_nonzero_integer(path),
99 };
100 Some(PrimitiveType::Integer {
101 zeroable: true,
102 signed,
103 kind,
104 })
105 }
106
107 fn maybe_nonzero_integer(path: &str) -> Option<PrimitiveType> {
112 let (kind, signed) = match path {
113 "NonZeroU8" => (IntKind::B8, false),
114 "NonZeroU16" => (IntKind::B16, false),
115 "NonZeroU32" => (IntKind::B32, false),
116 "NonZeroU64" => (IntKind::B64, false),
117 "NonZeroUSize" => (IntKind::Size, false),
118 "NonZeroI8" => (IntKind::B8, true),
119 "NonZeroI16" => (IntKind::B16, true),
120 "NonZeroI32" => (IntKind::B32, true),
121 "NonZeroI64" => (IntKind::B64, true),
122 "NonZeroISize" => (IntKind::Size, true),
123
124 _ => return None,
125 };
126 Some(PrimitiveType::Integer {
127 zeroable: false,
128 signed,
129 kind,
130 })
131 }
132
133 pub fn to_repr_rust(&self) -> &'static str {
134 match *self {
135 PrimitiveType::Bool => "bool",
136 PrimitiveType::Void => "c_void",
137 PrimitiveType::Char => "c_char",
138 PrimitiveType::SChar => "c_schar",
139 PrimitiveType::UChar => "c_uchar",
140 PrimitiveType::Char32 => "char",
141 PrimitiveType::Integer {
142 kind,
143 signed,
144 zeroable: _,
145 } => match (kind, signed) {
146 (IntKind::Short, true) => "c_short",
147 (IntKind::Short, false) => "c_ushort",
148 (IntKind::Int, true) => "c_int",
149 (IntKind::Int, false) => "c_uint",
150 (IntKind::Long, true) => "c_long",
151 (IntKind::Long, false) => "c_ulong",
152 (IntKind::LongLong, true) => "c_longlong",
153 (IntKind::LongLong, false) => "c_ulonglong",
154 (IntKind::SizeT, true) => "ssize_t",
155 (IntKind::SizeT, false) => "size_t",
156 (IntKind::Size, true) => "isize",
157 (IntKind::Size, false) => "usize",
158 (IntKind::B8, true) => "i8",
159 (IntKind::B8, false) => "u8",
160 (IntKind::B16, true) => "i16",
161 (IntKind::B16, false) => "u16",
162 (IntKind::B32, true) => "i32",
163 (IntKind::B32, false) => "u32",
164 (IntKind::B64, true) => "i64",
165 (IntKind::B64, false) => "u64",
166 },
167 PrimitiveType::Float => "f32",
168 PrimitiveType::Double => "f64",
169 PrimitiveType::PtrDiffT => "ptrdiff_t",
170 PrimitiveType::VaList => "va_list",
171 }
172 }
173
174 pub fn to_repr_c(&self, config: &Config) -> &'static str {
175 match *self {
176 PrimitiveType::Void => "void",
177 PrimitiveType::Bool => "bool",
178 PrimitiveType::Char => "char",
179 PrimitiveType::SChar => "signed char",
180 PrimitiveType::UChar => "unsigned char",
181 PrimitiveType::Char32 => "uint32_t",
190 PrimitiveType::Integer {
191 kind,
192 signed,
193 zeroable: _,
194 } => match (kind, signed) {
195 (IntKind::Short, true) => "short",
196 (IntKind::Short, false) => "unsigned short",
197 (IntKind::Int, true) => "int",
198 (IntKind::Int, false) => "unsigned int",
199 (IntKind::Long, true) => "long",
200 (IntKind::Long, false) => "unsigned long",
201 (IntKind::LongLong, true) => "long long",
202 (IntKind::LongLong, false) => "unsigned long long",
203 (IntKind::SizeT, true) => "ssize_t",
204 (IntKind::SizeT, false) => "size_t",
205 (IntKind::Size, true) if config.usize_is_size_t => "ptrdiff_t",
206 (IntKind::Size, false) if config.usize_is_size_t => "size_t",
207 (IntKind::Size, true) => "intptr_t",
208 (IntKind::Size, false) => "uintptr_t",
209 (IntKind::B8, true) => "int8_t",
210 (IntKind::B8, false) => "uint8_t",
211 (IntKind::B16, true) => "int16_t",
212 (IntKind::B16, false) => "uint16_t",
213 (IntKind::B32, true) => "int32_t",
214 (IntKind::B32, false) => "uint32_t",
215 (IntKind::B64, true) => "int64_t",
216 (IntKind::B64, false) => "uint64_t",
217 },
218 PrimitiveType::Float => "float",
219 PrimitiveType::Double => "double",
220 PrimitiveType::PtrDiffT => "ptrdiff_t",
221 PrimitiveType::VaList => "...",
222 }
223 }
224
225 fn can_cmp_order(&self) -> bool {
226 !matches!(*self, PrimitiveType::Bool)
227 }
228
229 fn can_cmp_eq(&self) -> bool {
230 true
231 }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
239pub enum ConstExpr {
240 Name(String),
241 Value(String),
242}
243
244impl ConstExpr {
245 pub fn as_str(&self) -> &str {
246 match *self {
247 ConstExpr::Name(ref string) | ConstExpr::Value(ref string) => string,
248 }
249 }
250
251 pub fn rename_for_config(&mut self, config: &Config) {
252 if let ConstExpr::Name(ref mut name) = self {
253 config.export.rename(name);
254 }
255 }
256
257 pub fn load(expr: &syn::Expr) -> Result<Self, String> {
258 match *expr {
259 syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => {
260 let val = match *lit {
261 syn::Lit::Bool(syn::LitBool { value, .. }) => value.to_string(),
262 syn::Lit::Int(ref len) => len.base10_digits().to_string(),
263 syn::Lit::Byte(ref byte) => u8::to_string(&byte.value()),
264 syn::Lit::Char(ref ch) => u32::to_string(&ch.value().into()),
265 _ => return Err(format!("can't handle const expression {lit:?}")),
266 };
267 Ok(ConstExpr::Value(val))
268 }
269 syn::Expr::Path(ref path) => {
270 let generic_path = GenericPath::load(&path.path)?;
271 Ok(ConstExpr::Name(generic_path.export_name().to_owned()))
272 }
273 syn::Expr::Cast(ref cast) => Ok(ConstExpr::load(&cast.expr)?),
274 _ => Err(format!("can't handle const expression {expr:?}")),
275 }
276 }
277
278 pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> ConstExpr {
279 match *self {
280 ConstExpr::Name(ref name) => {
281 let path = Path::new(name);
282 for &(param, value) in mappings {
283 if path == *param {
284 match *value {
285 GenericArgument::Type(Type::Path(ref path))
286 if path.is_single_identifier() =>
287 {
288 return ConstExpr::Name(path.name().to_string());
290 }
291 GenericArgument::Const(ref expr) => {
292 return expr.clone();
293 }
294 _ => {
295 }
297 }
298 }
299 }
300 }
301 ConstExpr::Value(_) => {}
302 }
303 self.clone()
304 }
305}
306
307#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
308pub enum Type {
309 Ptr {
310 ty: Box<Type>,
311 is_const: bool,
312 is_nullable: bool,
313 is_ref: bool,
317 },
318 Path(GenericPath),
319 Primitive(PrimitiveType),
320 Array(Box<Type>, ConstExpr),
321 FuncPtr {
322 ret: Box<Type>,
323 args: Vec<(Option<String>, Type)>,
324 is_nullable: bool,
325 never_return: bool,
326 },
327}
328
329impl Type {
330 pub fn const_ref_to(ty: &Self) -> Self {
331 Type::Ptr {
332 ty: Box::new(ty.clone()),
333 is_const: true,
334 is_nullable: false,
335 is_ref: true,
336 }
337 }
338
339 pub fn load_from_output(output: &syn::ReturnType) -> Result<(Type, bool), String> {
340 let mut never_return = false;
341 let ty = match output {
342 syn::ReturnType::Default => Type::Primitive(PrimitiveType::Void),
343 syn::ReturnType::Type(_, ref ty) => {
344 if let syn::Type::Never(_) = ty.as_ref() {
345 never_return = true;
346 Type::Primitive(PrimitiveType::Void)
347 } else {
348 Type::load(ty)?.unwrap_or(Type::Primitive(PrimitiveType::Void))
349 }
350 }
351 };
352 Ok((ty, never_return))
353 }
354
355 pub fn load(ty: &syn::Type) -> Result<Option<Type>, String> {
356 let converted = match *ty {
357 syn::Type::Reference(ref reference) => {
358 let converted = Type::load(&reference.elem)?;
359
360 let converted = match converted {
361 Some(converted) => converted,
362 None => Type::Primitive(PrimitiveType::Void),
363 };
364
365 let is_const = reference.mutability.is_none();
367 Type::Ptr {
368 ty: Box::new(converted),
369 is_const,
370 is_nullable: false,
371 is_ref: false,
372 }
373 }
374 syn::Type::Ptr(ref pointer) => {
375 let converted = Type::load(&pointer.elem)?;
376
377 let converted = match converted {
378 Some(converted) => converted,
379 None => Type::Primitive(PrimitiveType::Void),
380 };
381
382 let is_const = pointer.mutability.is_none();
383 Type::Ptr {
384 ty: Box::new(converted),
385 is_const,
386 is_nullable: true,
387 is_ref: false,
388 }
389 }
390 syn::Type::Path(ref path) => {
391 let generic_path = GenericPath::load(&path.path)?;
392
393 if generic_path.name() == "PhantomData" || generic_path.name() == "PhantomPinned" {
394 return Ok(None);
395 }
396
397 if let Some(prim) = PrimitiveType::maybe(generic_path.name()) {
398 if !generic_path.generics().is_empty() {
399 return Err("Primitive has generics.".to_owned());
400 }
401 Type::Primitive(prim)
402 } else {
403 Type::Path(generic_path)
404 }
405 }
406 syn::Type::Array(syn::TypeArray {
407 ref elem, ref len, ..
408 }) => {
409 let converted = Type::load(elem)?;
410
411 let converted = match converted {
412 Some(converted) => converted,
413 None => return Err("Cannot have an array of zero sized types.".to_owned()),
414 };
415
416 let len = ConstExpr::load(len)?;
417 Type::Array(Box::new(converted), len)
418 }
419 syn::Type::BareFn(ref function) => {
420 let mut wildcard_counter = 0;
421 let mut args = function.inputs.iter().try_skip_map(|x| {
422 Type::load(&x.ty).map(|opt_ty| {
423 opt_ty.map(|ty| {
424 (
425 x.name.as_ref().map(|(ref ident, _)| {
426 if ident == "_" {
427 wildcard_counter += 1;
428 if wildcard_counter == 1 {
429 "_".to_owned()
430 } else {
431 format!("_{}", wildcard_counter - 1)
432 }
433 } else {
434 ident.unraw().to_string()
435 }
436 }),
437 ty,
438 )
439 })
440 })
441 })?;
442 if function.variadic.is_some() {
443 args.push((None, Type::Primitive(super::PrimitiveType::VaList)))
444 }
445 let (ret, never_return) = Type::load_from_output(&function.output)?;
446 Type::FuncPtr {
447 ret: Box::new(ret),
448 args,
449 is_nullable: false,
450 never_return,
451 }
452 }
453 syn::Type::Tuple(ref tuple) => {
454 if tuple.elems.is_empty() {
455 return Ok(None);
456 }
457 return Err("Tuples are not supported types.".to_owned());
458 }
459 syn::Type::Verbatim(ref tokens) if tokens.to_string() == "..." => {
460 Type::Primitive(PrimitiveType::VaList)
461 }
462 _ => return Err(format!("Unsupported type: {ty:?}")),
463 };
464
465 Ok(Some(converted))
466 }
467
468 pub fn is_ptr(&self) -> bool {
469 matches!(*self, Type::Ptr { .. } | Type::FuncPtr { .. })
470 }
471
472 pub fn is_primitive_or_ptr_primitive(&self) -> bool {
473 match *self {
474 Type::Primitive(..) => true,
475 Type::Ptr { ref ty, .. } => matches!(ty.as_ref(), Type::Primitive(..)),
476 _ => false,
477 }
478 }
479
480 pub fn make_zeroable(&self, new_zeroable: bool) -> Option<Self> {
481 match *self {
482 Type::Primitive(PrimitiveType::Integer {
483 zeroable: old_zeroable,
484 kind,
485 signed,
486 }) if old_zeroable != new_zeroable => Some(Type::Primitive(PrimitiveType::Integer {
487 kind,
488 signed,
489 zeroable: new_zeroable,
490 })),
491 _ => None,
492 }
493 }
494
495 pub fn make_nullable(&self) -> Option<Self> {
496 match *self {
497 Type::Ptr {
498 ref ty,
499 is_const,
500 is_ref,
501 is_nullable: false,
502 } => Some(Type::Ptr {
503 ty: ty.clone(),
504 is_const,
505 is_ref,
506 is_nullable: true,
507 }),
508 Type::FuncPtr {
509 ref ret,
510 ref args,
511 is_nullable: false,
512 never_return,
513 } => Some(Type::FuncPtr {
514 ret: ret.clone(),
515 args: args.clone(),
516 is_nullable: true,
517 never_return,
518 }),
519 _ => None,
520 }
521 }
522
523 fn simplified_type(&self, config: &Config) -> Option<Self> {
524 let path = match *self {
525 Type::Path(ref p) => p,
526 _ => return None,
527 };
528
529 if path.generics().is_empty() {
530 return None;
531 }
532
533 if path.generics().len() != 1 {
534 return None;
535 }
536
537 let unsimplified_generic = match path.generics()[0] {
538 GenericArgument::Type(ref ty) => ty,
539 GenericArgument::Const(_) => return None,
540 };
541
542 let generic = match unsimplified_generic.simplified_type(config) {
543 Some(generic) => Cow::Owned(generic),
544 None => Cow::Borrowed(unsimplified_generic),
545 };
546 match path.name() {
547 "Option" => generic
548 .make_nullable()
549 .or_else(|| generic.make_zeroable(true)),
550 "NonNull" => Some(Type::Ptr {
551 ty: Box::new(generic.into_owned()),
552 is_const: false,
553 is_nullable: false,
554 is_ref: false,
555 }),
556 "NonZero" => generic.make_zeroable(false),
557 "Box" if config.language != Language::Cxx => Some(Type::Ptr {
558 ty: Box::new(generic.into_owned()),
559 is_const: false,
560 is_nullable: false,
561 is_ref: false,
562 }),
563 "SyncUnsafeCell" | "UnsafeCell" | "Cell" => Some(generic.into_owned()),
564 "ManuallyDrop" | "MaybeUninit" | "Pin" if config.language != Language::Cxx => {
565 Some(generic.into_owned())
566 }
567 _ => None,
568 }
569 }
570
571 pub fn simplify_standard_types(&mut self, config: &Config) {
572 self.visit_types(|ty| ty.simplify_standard_types(config));
573 if let Some(ty) = self.simplified_type(config) {
574 *self = ty;
575 }
576 }
577
578 pub fn replace_self_with(&mut self, self_ty: &Path) {
579 if let Type::Path(ref mut generic_path) = *self {
580 generic_path.replace_self_with(self_ty);
581 }
582 self.visit_types(|ty| ty.replace_self_with(self_ty))
583 }
584
585 fn visit_types(&mut self, mut visitor: impl FnMut(&mut Type)) {
586 match *self {
587 Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty),
588 Type::Path(ref mut path) => {
589 for generic in path.generics_mut() {
590 match *generic {
591 GenericArgument::Type(ref mut ty) => visitor(ty),
592 GenericArgument::Const(_) => {}
593 }
594 }
595 }
596 Type::Primitive(..) => {}
597 Type::FuncPtr {
598 ref mut ret,
599 ref mut args,
600 ..
601 } => {
602 visitor(ret);
603 for arg in args {
604 visitor(&mut arg.1)
605 }
606 }
607 }
608 }
609
610 pub fn get_root_path(&self) -> Option<Path> {
611 let mut current = self;
612 loop {
613 match *current {
614 Type::Ptr { ref ty, .. } => current = ty,
615 Type::Path(ref generic) => {
616 return Some(generic.path().clone());
617 }
618 Type::Primitive(..) => {
619 return None;
620 }
621 Type::Array(..) => {
622 return None;
623 }
624 Type::FuncPtr { .. } => {
625 return None;
626 }
627 };
628 }
629 }
630
631 pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> Type {
632 match *self {
633 Type::Ptr {
634 ref ty,
635 is_const,
636 is_nullable,
637 is_ref,
638 } => Type::Ptr {
639 ty: Box::new(ty.specialize(mappings)),
640 is_const,
641 is_nullable,
642 is_ref,
643 },
644 Type::Path(ref generic_path) => {
645 for &(param, value) in mappings {
646 if generic_path.path() == param {
647 if let GenericArgument::Type(ref ty) = *value {
648 return ty.clone();
649 }
650 }
651 }
652
653 let specialized = GenericPath::new(
654 generic_path.path().clone(),
655 generic_path
656 .generics()
657 .iter()
658 .map(|x| x.specialize(mappings))
659 .collect(),
660 );
661 Type::Path(specialized)
662 }
663 Type::Primitive(ref primitive) => Type::Primitive(primitive.clone()),
664 Type::Array(ref ty, ref constant) => Type::Array(
665 Box::new(ty.specialize(mappings)),
666 constant.specialize(mappings),
667 ),
668 Type::FuncPtr {
669 ref ret,
670 ref args,
671 is_nullable,
672 never_return,
673 } => Type::FuncPtr {
674 ret: Box::new(ret.specialize(mappings)),
675 args: args
676 .iter()
677 .cloned()
678 .map(|(name, ty)| (name, ty.specialize(mappings)))
679 .collect(),
680 is_nullable,
681 never_return,
682 },
683 }
684 }
685
686 pub fn add_dependencies_ignoring_generics(
687 &self,
688 generic_params: &GenericParams,
689 library: &Library,
690 out: &mut Dependencies,
691 ) {
692 match *self {
693 Type::Ptr { ref ty, .. } => {
694 ty.add_dependencies_ignoring_generics(generic_params, library, out);
695 }
696 Type::Path(ref generic) => {
697 for generic_value in generic.generics() {
698 if let GenericArgument::Type(ref ty) = *generic_value {
699 ty.add_dependencies_ignoring_generics(generic_params, library, out);
700 }
701 }
702 let path = generic.path();
703 if !generic_params.iter().any(|param| param.name() == path) {
704 out.add(library, path);
705 }
706 }
707 Type::Primitive(_) => {}
708 Type::Array(ref ty, _) => {
709 ty.add_dependencies_ignoring_generics(generic_params, library, out);
710 }
711 Type::FuncPtr {
712 ref ret, ref args, ..
713 } => {
714 ret.add_dependencies_ignoring_generics(generic_params, library, out);
715 for (_, ref arg) in args {
716 arg.add_dependencies_ignoring_generics(generic_params, library, out);
717 }
718 }
719 }
720 }
721
722 pub fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
723 self.add_dependencies_ignoring_generics(&GenericParams::default(), library, out)
724 }
725
726 pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
727 match *self {
728 Type::Ptr { ref ty, .. } => {
729 ty.add_monomorphs(library, out);
730 }
731 Type::Path(ref generic) => {
732 if generic.generics().is_empty() || out.contains(generic) {
733 return;
734 }
735 let path = generic.path();
736 if let Some(items) = library.get_items(path) {
737 for item in items {
738 item.deref()
739 .instantiate_monomorph(generic.generics(), library, out);
740 }
741 }
742 }
743 Type::Primitive(_) => {}
744 Type::Array(ref ty, _) => {
745 ty.add_monomorphs(library, out);
746 }
747 Type::FuncPtr {
748 ref ret, ref args, ..
749 } => {
750 ret.add_monomorphs(library, out);
751 for (_, ref arg) in args {
752 arg.add_monomorphs(library, out);
753 }
754 }
755 }
756 }
757
758 pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
759 match *self {
760 Type::Ptr { ref mut ty, .. } => {
761 ty.rename_for_config(config, generic_params);
762 }
763 Type::Path(ref mut ty) => {
764 ty.rename_for_config(config, generic_params);
765 }
766 Type::Primitive(_) => {}
767 Type::Array(ref mut ty, ref mut len) => {
768 ty.rename_for_config(config, generic_params);
769 len.rename_for_config(config);
770 }
771 Type::FuncPtr {
772 ref mut ret,
773 ref mut args,
774 ..
775 } => {
776 ret.rename_for_config(config, generic_params);
777 for (_, arg) in args {
778 arg.rename_for_config(config, generic_params);
779 }
780 }
781 }
782 }
783
784 pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
785 match *self {
786 Type::Ptr { ref mut ty, .. } => {
787 ty.resolve_declaration_types(resolver);
788 }
789 Type::Path(ref mut generic_path) => {
790 generic_path.resolve_declaration_types(resolver);
791 }
792 Type::Primitive(_) => {}
793 Type::Array(ref mut ty, _) => {
794 ty.resolve_declaration_types(resolver);
795 }
796 Type::FuncPtr {
797 ref mut ret,
798 ref mut args,
799 ..
800 } => {
801 ret.resolve_declaration_types(resolver);
802 for (_, ref mut arg) in args {
803 arg.resolve_declaration_types(resolver);
804 }
805 }
806 }
807 }
808
809 pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
810 match *self {
811 Type::Ptr { ref mut ty, .. } => {
812 ty.mangle_paths(monomorphs);
813 }
814 Type::Path(ref mut generic_path) => {
815 if generic_path.generics().is_empty() {
816 return;
817 }
818
819 if let Some(mangled_path) = monomorphs.mangle_path(generic_path) {
820 *generic_path = GenericPath::new(mangled_path.clone(), vec![]);
821 } else {
822 warn!(
823 "Cannot find a mangling for generic path {generic_path:?}. This usually means that a \
824 type referenced by this generic was incompatible or not found."
825 );
826 }
827 }
828 Type::Primitive(_) => {}
829 Type::Array(ref mut ty, _) => {
830 ty.mangle_paths(monomorphs);
831 }
832 Type::FuncPtr {
833 ref mut ret,
834 ref mut args,
835 ..
836 } => {
837 ret.mangle_paths(monomorphs);
838 for (_, ref mut arg) in args {
839 arg.mangle_paths(monomorphs);
840 }
841 }
842 }
843 }
844
845 pub fn can_cmp_order(&self) -> bool {
846 match *self {
847 Type::Ptr { is_ref, .. } => !is_ref,
849 Type::Path(..) => true,
850 Type::Primitive(ref p) => p.can_cmp_order(),
851 Type::Array(..) => false,
852 Type::FuncPtr { .. } => false,
853 }
854 }
855
856 pub fn can_cmp_eq(&self) -> bool {
857 match *self {
858 Type::Ptr { ref ty, is_ref, .. } => !is_ref || ty.can_cmp_eq(),
859 Type::Path(..) => true,
860 Type::Primitive(ref p) => p.can_cmp_eq(),
861 Type::Array(..) => false,
862 Type::FuncPtr { .. } => true,
863 }
864 }
865}