1use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
4use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
5use super::annotations::Annotations;
6use super::comp::{CompKind, MethodKind};
7use super::context::{BindgenContext, ItemId, PartialType, TypeId};
8use super::derive::{
9 CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
10 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
11};
12use super::dot::DotAttributes;
13use super::function::{Function, FunctionKind};
14use super::item_kind::ItemKind;
15use super::layout::Opaque;
16use super::module::Module;
17use super::template::{AsTemplateParam, TemplateParameters};
18use super::traversal::{EdgeKind, Trace, Tracer};
19use super::ty::{Type, TypeKind};
20use crate::clang;
21use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
22
23use std::cell::{Cell, OnceCell};
24use std::collections::BTreeSet;
25use std::fmt::Write;
26use std::io;
27use std::iter;
28use std::sync::OnceLock;
29
30pub(crate) trait ItemCanonicalName {
41 fn canonical_name(&self, ctx: &BindgenContext) -> String;
43}
44
45pub(crate) trait ItemCanonicalPath {
58 fn namespace_aware_canonical_path(
62 &self,
63 ctx: &BindgenContext,
64 ) -> Vec<String>;
65
66 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
68}
69
70pub(crate) trait IsOpaque {
72 type Extra;
74
75 fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
79}
80
81pub(crate) trait HasTypeParamInArray {
83 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool;
85}
86
87pub(crate) trait ItemAncestors {
90 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
92}
93
94#[cfg(feature = "__testing_only_extra_assertions")]
95type DebugOnlyItemSet = ItemSet;
96
97#[cfg(not(feature = "__testing_only_extra_assertions"))]
98struct DebugOnlyItemSet;
99
100#[cfg(not(feature = "__testing_only_extra_assertions"))]
101impl DebugOnlyItemSet {
102 fn new() -> Self {
103 DebugOnlyItemSet
104 }
105
106 fn contains(&self, _id: &ItemId) -> bool {
107 false
108 }
109
110 fn insert(&mut self, _id: ItemId) {}
111}
112
113pub(crate) struct ItemAncestorsIter<'a> {
115 item: ItemId,
116 ctx: &'a BindgenContext,
117 seen: DebugOnlyItemSet,
118}
119
120impl<'a> ItemAncestorsIter<'a> {
121 fn new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self {
122 ItemAncestorsIter {
123 item: id.into(),
124 ctx,
125 seen: DebugOnlyItemSet::new(),
126 }
127 }
128}
129
130impl Iterator for ItemAncestorsIter<'_> {
131 type Item = ItemId;
132
133 fn next(&mut self) -> Option<Self::Item> {
134 let item = self.ctx.resolve_item(self.item);
135
136 if item.parent_id() == self.item {
137 None
138 } else {
139 self.item = item.parent_id();
140
141 extra_assert!(!self.seen.contains(&item.id()));
142 self.seen.insert(item.id());
143
144 Some(item.id())
145 }
146 }
147}
148
149impl<T> AsTemplateParam for T
150where
151 T: Copy + Into<ItemId>,
152{
153 type Extra = ();
154
155 fn as_template_param(
156 &self,
157 ctx: &BindgenContext,
158 _: &(),
159 ) -> Option<TypeId> {
160 ctx.resolve_item((*self).into()).as_template_param(ctx, &())
161 }
162}
163
164impl AsTemplateParam for Item {
165 type Extra = ();
166
167 fn as_template_param(
168 &self,
169 ctx: &BindgenContext,
170 _: &(),
171 ) -> Option<TypeId> {
172 self.kind.as_template_param(ctx, self)
173 }
174}
175
176impl AsTemplateParam for ItemKind {
177 type Extra = Item;
178
179 fn as_template_param(
180 &self,
181 ctx: &BindgenContext,
182 item: &Item,
183 ) -> Option<TypeId> {
184 match *self {
185 ItemKind::Type(ref ty) => ty.as_template_param(ctx, item),
186 ItemKind::Module(..) |
187 ItemKind::Function(..) |
188 ItemKind::Var(..) => None,
189 }
190 }
191}
192
193impl<T> ItemCanonicalName for T
194where
195 T: Copy + Into<ItemId>,
196{
197 fn canonical_name(&self, ctx: &BindgenContext) -> String {
198 debug_assert!(
199 ctx.in_codegen_phase(),
200 "You're not supposed to call this yet"
201 );
202 ctx.resolve_item(*self).canonical_name(ctx)
203 }
204}
205
206impl<T> ItemCanonicalPath for T
207where
208 T: Copy + Into<ItemId>,
209{
210 fn namespace_aware_canonical_path(
211 &self,
212 ctx: &BindgenContext,
213 ) -> Vec<String> {
214 debug_assert!(
215 ctx.in_codegen_phase(),
216 "You're not supposed to call this yet"
217 );
218 ctx.resolve_item(*self).namespace_aware_canonical_path(ctx)
219 }
220
221 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
222 debug_assert!(
223 ctx.in_codegen_phase(),
224 "You're not supposed to call this yet"
225 );
226 ctx.resolve_item(*self).canonical_path(ctx)
227 }
228}
229
230impl<T> ItemAncestors for T
231where
232 T: Copy + Into<ItemId>,
233{
234 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
235 ItemAncestorsIter::new(ctx, *self)
236 }
237}
238
239impl ItemAncestors for Item {
240 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
241 self.id().ancestors(ctx)
242 }
243}
244
245impl<Id> Trace for Id
246where
247 Id: Copy + Into<ItemId>,
248{
249 type Extra = ();
250
251 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &())
252 where
253 T: Tracer,
254 {
255 ctx.resolve_item(*self).trace(ctx, tracer, extra);
256 }
257}
258
259impl Trace for Item {
260 type Extra = ();
261
262 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &())
263 where
264 T: Tracer,
265 {
266 match *self.kind() {
274 ItemKind::Type(ref ty) => {
275 if ty.should_be_traced_unconditionally() ||
279 !self.is_opaque(ctx, &())
280 {
281 ty.trace(ctx, tracer, self);
282 }
283 }
284 ItemKind::Function(ref fun) => {
285 tracer.visit(fun.signature().into());
288 }
289 ItemKind::Var(ref var) => {
290 tracer.visit_kind(var.ty().into(), EdgeKind::VarType);
291 }
292 ItemKind::Module(_) => {
293 }
301 }
302 }
303}
304
305impl CanDeriveDebug for Item {
306 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
307 self.id().can_derive_debug(ctx)
308 }
309}
310
311impl CanDeriveDefault for Item {
312 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
313 self.id().can_derive_default(ctx)
314 }
315}
316
317impl CanDeriveCopy for Item {
318 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
319 self.id().can_derive_copy(ctx)
320 }
321}
322
323impl CanDeriveHash for Item {
324 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
325 self.id().can_derive_hash(ctx)
326 }
327}
328
329impl CanDerivePartialOrd for Item {
330 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
331 self.id().can_derive_partialord(ctx)
332 }
333}
334
335impl CanDerivePartialEq for Item {
336 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
337 self.id().can_derive_partialeq(ctx)
338 }
339}
340
341impl CanDeriveEq for Item {
342 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
343 self.id().can_derive_eq(ctx)
344 }
345}
346
347impl CanDeriveOrd for Item {
348 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
349 self.id().can_derive_ord(ctx)
350 }
351}
352
353#[derive(Debug)]
371pub(crate) struct Item {
372 id: ItemId,
374
375 local_id: OnceCell<usize>,
383
384 next_child_local_id: Cell<usize>,
386
387 canonical_name: OnceCell<String>,
392
393 path_for_allowlisting: OnceCell<Vec<String>>,
396
397 comment: Option<String>,
399 annotations: Annotations,
402 parent_id: ItemId,
408 kind: ItemKind,
410 location: Option<clang::SourceLocation>,
412}
413
414impl AsRef<ItemId> for Item {
415 fn as_ref(&self) -> &ItemId {
416 &self.id
417 }
418}
419
420impl Item {
421 pub(crate) fn new(
423 id: ItemId,
424 comment: Option<String>,
425 annotations: Option<Annotations>,
426 parent_id: ItemId,
427 kind: ItemKind,
428 location: Option<clang::SourceLocation>,
429 ) -> Self {
430 debug_assert!(id != parent_id || kind.is_module());
431 Item {
432 id,
433 local_id: OnceCell::new(),
434 next_child_local_id: Cell::new(1),
435 canonical_name: OnceCell::new(),
436 path_for_allowlisting: OnceCell::new(),
437 parent_id,
438 comment,
439 annotations: annotations.unwrap_or_default(),
440 kind,
441 location,
442 }
443 }
444
445 pub(crate) fn new_opaque_type(
447 with_id: ItemId,
448 ty: &clang::Type,
449 ctx: &mut BindgenContext,
450 ) -> TypeId {
451 let location = ty.declaration().location();
452 let ty = Opaque::from_clang_ty(ty, ctx);
453 let kind = ItemKind::Type(ty);
454 let parent = ctx.root_module().into();
455 ctx.add_item(
456 Item::new(with_id, None, None, parent, kind, Some(location)),
457 None,
458 None,
459 );
460 with_id.as_type_id_unchecked()
461 }
462
463 pub(crate) fn id(&self) -> ItemId {
465 self.id
466 }
467
468 pub(crate) fn parent_id(&self) -> ItemId {
472 self.parent_id
473 }
474
475 pub(crate) fn set_parent_for_replacement<Id: Into<ItemId>>(
479 &mut self,
480 id: Id,
481 ) {
482 self.parent_id = id.into();
483 }
484
485 pub(crate) fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
489 if !ctx.options().enable_cxx_namespaces {
490 return 0;
491 }
492
493 self.ancestors(ctx)
494 .filter(|id| {
495 ctx.resolve_item(*id).as_module().is_some_and(|module| {
496 !module.is_inline() ||
497 ctx.options().conservative_inline_namespaces
498 })
499 })
500 .count() +
501 1
502 }
503
504 pub(crate) fn comment(&self, ctx: &BindgenContext) -> Option<String> {
507 if !ctx.options().generate_comments {
508 return None;
509 }
510
511 self.comment
512 .as_ref()
513 .map(|comment| ctx.options().process_comment(comment))
514 }
515
516 pub(crate) fn kind(&self) -> &ItemKind {
518 &self.kind
519 }
520
521 pub(crate) fn kind_mut(&mut self) -> &mut ItemKind {
523 &mut self.kind
524 }
525
526 pub(crate) fn location(&self) -> Option<&clang::SourceLocation> {
528 self.location.as_ref()
529 }
530
531 pub(crate) fn local_id(&self, ctx: &BindgenContext) -> usize {
537 *self.local_id.get_or_init(|| {
538 let parent = ctx.resolve_item(self.parent_id);
539 parent.next_child_local_id()
540 })
541 }
542
543 pub(crate) fn next_child_local_id(&self) -> usize {
550 let local_id = self.next_child_local_id.get();
551 self.next_child_local_id.set(local_id + 1);
552 local_id
553 }
554
555 pub(crate) fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
574 if ctx.options().enable_cxx_namespaces &&
577 self.kind().is_module() &&
578 self.id() != ctx.root_module()
579 {
580 return false;
581 }
582
583 let mut parent = self.parent_id;
584 loop {
585 let Some(parent_item) = ctx.resolve_item_fallible(parent) else {
586 return false;
587 };
588
589 if parent_item.id() == ctx.root_module() {
590 return true;
591 } else if ctx.options().enable_cxx_namespaces ||
592 !parent_item.kind().is_module()
593 {
594 return false;
595 }
596
597 parent = parent_item.parent_id();
598 }
599 }
600
601 pub(crate) fn expect_type(&self) -> &Type {
604 self.kind().expect_type()
605 }
606
607 pub(crate) fn as_type(&self) -> Option<&Type> {
610 self.kind().as_type()
611 }
612
613 pub(crate) fn expect_function(&self) -> &Function {
616 self.kind().expect_function()
617 }
618
619 pub(crate) fn is_module(&self) -> bool {
621 matches!(self.kind, ItemKind::Module(..))
622 }
623
624 pub(crate) fn annotations(&self) -> &Annotations {
626 &self.annotations
627 }
628
629 pub(crate) fn is_blocklisted(&self, ctx: &BindgenContext) -> bool {
633 debug_assert!(
634 ctx.in_codegen_phase(),
635 "You're not supposed to call this yet"
636 );
637 if self.annotations.hide() {
638 return true;
639 }
640
641 if !ctx.options().blocklisted_files.is_empty() {
642 if let Some(location) = &self.location {
643 let (file, _, _, _) = location.location();
644 if let Some(filename) = file.name() {
645 if ctx.options().blocklisted_files.matches(filename) {
646 return true;
647 }
648 }
649 }
650 }
651
652 let path = self.path_for_allowlisting(ctx);
653 let name = path[1..].join("::");
654 ctx.options().blocklisted_items.matches(&name) ||
655 match self.kind {
656 ItemKind::Type(..) => {
657 ctx.options().blocklisted_types.matches(&name) ||
658 ctx.is_replaced_type(path, self.id)
659 }
660 ItemKind::Function(..) => {
661 ctx.options().blocklisted_functions.matches(&name)
662 }
663 ItemKind::Var(..) => {
664 ctx.options().blocklisted_vars.matches(&name)
665 }
666 ItemKind::Module(..) => false,
668 }
669 }
670
671 pub(crate) fn name<'a>(
673 &'a self,
674 ctx: &'a BindgenContext,
675 ) -> NameOptions<'a> {
676 NameOptions::new(self, ctx)
677 }
678
679 fn name_target(&self, ctx: &BindgenContext) -> ItemId {
681 let mut targets_seen = DebugOnlyItemSet::new();
682 let mut item = self;
683
684 loop {
685 extra_assert!(!targets_seen.contains(&item.id()));
686 targets_seen.insert(item.id());
687
688 if self.annotations().use_instead_of().is_some() {
689 return self.id();
690 }
691
692 match *item.kind() {
693 ItemKind::Type(ref ty) => match *ty.kind() {
694 TypeKind::ResolvedTypeRef(inner) => {
695 item = ctx.resolve_item(inner);
696 }
697 TypeKind::TemplateInstantiation(ref inst) => {
698 item = ctx.resolve_item(inst.template_definition());
699 }
700 _ => return item.id(),
701 },
702 _ => return item.id(),
703 }
704 }
705 }
706
707 pub(crate) fn full_disambiguated_name(
710 &self,
711 ctx: &BindgenContext,
712 ) -> String {
713 let mut s = String::new();
714 let level = 0;
715 self.push_disambiguated_name(ctx, &mut s, level);
716 s
717 }
718
719 fn push_disambiguated_name(
721 &self,
722 ctx: &BindgenContext,
723 to: &mut String,
724 level: u8,
725 ) {
726 to.push_str(&self.canonical_name(ctx));
727 if let ItemKind::Type(ref ty) = *self.kind() {
728 if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() {
729 to.push_str(&format!("_open{level}_"));
730 for arg in inst.template_arguments() {
731 arg.into_resolver()
732 .through_type_refs()
733 .resolve(ctx)
734 .push_disambiguated_name(ctx, to, level + 1);
735 to.push('_');
736 }
737 to.push_str(&format!("close{level}"));
738 }
739 }
740 }
741
742 fn func_name(&self) -> Option<&str> {
744 match *self.kind() {
745 ItemKind::Function(ref func) => Some(func.name()),
746 _ => None,
747 }
748 }
749
750 fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> {
753 self.func_name().and_then(|func_name| {
754 let parent = ctx.resolve_item(self.parent_id());
755 if let ItemKind::Type(ref ty) = *parent.kind() {
756 if let TypeKind::Comp(ref ci) = *ty.kind() {
757 return ci
760 .constructors()
761 .iter()
762 .position(|c| *c == self.id())
763 .or_else(|| {
764 ci.methods()
765 .iter()
766 .filter(|m| {
767 let item = ctx.resolve_item(m.signature());
768 let func = item.expect_function();
769 func.name() == func_name
770 })
771 .position(|m| m.signature() == self.id())
772 });
773 }
774 }
775
776 None
777 })
778 }
779
780 fn base_name(&self, ctx: &BindgenContext) -> String {
782 if let Some(path) = self.annotations().use_instead_of() {
783 return path.last().unwrap().clone();
784 }
785
786 match *self.kind() {
787 ItemKind::Var(ref var) => var.name().to_owned(),
788 ItemKind::Module(ref module) => module.name().map_or_else(
789 || format!("_bindgen_mod_{}", self.exposed_id(ctx)),
790 ToOwned::to_owned,
791 ),
792 ItemKind::Type(ref ty) => ty.sanitized_name(ctx).map_or_else(
793 || format!("_bindgen_ty_{}", self.exposed_id(ctx)),
794 Into::into,
795 ),
796 ItemKind::Function(ref fun) => {
797 let mut name = fun.name().to_owned();
798
799 if let Some(idx) = self.overload_index(ctx) {
800 if idx > 0 {
801 write!(&mut name, "{idx}").unwrap();
802 }
803 }
804
805 name
806 }
807 }
808 }
809
810 fn is_anon(&self) -> bool {
811 match self.kind() {
812 ItemKind::Module(module) => module.name().is_none(),
813 ItemKind::Type(ty) => ty.name().is_none(),
814 ItemKind::Function(_) => false,
815 ItemKind::Var(_) => false,
816 }
817 }
818
819 pub(crate) fn real_canonical_name(
835 &self,
836 ctx: &BindgenContext,
837 opt: &NameOptions,
838 ) -> String {
839 let target = ctx.resolve_item(self.name_target(ctx));
840
841 if let Some(path) = target.annotations.use_instead_of() {
843 if ctx.options().enable_cxx_namespaces {
844 return path.last().unwrap().clone();
845 }
846 return path.join("_");
847 }
848
849 let base_name = target.base_name(ctx);
850
851 if target.is_template_param(ctx, &()) {
854 return base_name;
855 }
856
857 let mut ids_iter = target
859 .parent_id()
860 .ancestors(ctx)
861 .filter(|id| *id != ctx.root_module())
862 .take_while(|id| {
863 !opt.within_namespaces || !ctx.resolve_item(*id).is_module()
866 })
867 .filter(|id| {
868 if !ctx.options().conservative_inline_namespaces {
869 if let ItemKind::Module(ref module) =
870 *ctx.resolve_item(*id).kind()
871 {
872 return !module.is_inline();
873 }
874 }
875
876 true
877 });
878
879 let ids: Vec<_> = if ctx.options().disable_nested_struct_naming {
880 let mut ids = Vec::new();
881
882 if target.is_anon() {
884 for id in ids_iter.by_ref() {
885 ids.push(id);
886
887 if !ctx.resolve_item(id).is_anon() {
888 break;
889 }
890 }
891 }
892
893 ids
894 } else {
895 ids_iter.collect()
896 };
897
898 let mut names: Vec<_> = ids
900 .into_iter()
901 .map(|id| {
902 let item = ctx.resolve_item(id);
903 let target = ctx.resolve_item(item.name_target(ctx));
904 target.base_name(ctx)
905 })
906 .filter(|name| !name.is_empty())
907 .collect();
908
909 names.reverse();
910
911 if !base_name.is_empty() {
912 names.push(base_name);
913 }
914
915 if ctx.options().c_naming {
916 if let Some(prefix) = self.c_naming_prefix() {
917 names.insert(0, prefix.to_string());
918 }
919 }
920
921 let name = names.join("_");
922
923 let name = if opt.user_mangled == UserMangled::Yes {
924 ctx.options()
925 .last_callback(|callbacks| callbacks.item_name(&name))
926 .unwrap_or(name)
927 } else {
928 name
929 };
930
931 ctx.rust_mangle(&name).into_owned()
932 }
933
934 pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String {
937 let ty_kind = self.kind().as_type().map(|t| t.kind());
940 if let Some(
941 TypeKind::Comp(..) |
942 TypeKind::TemplateInstantiation(..) |
943 TypeKind::Enum(..),
944 ) = ty_kind
945 {
946 return self.local_id(ctx).to_string();
947 }
948
949 format!("id_{}", self.id().as_usize())
953 }
954
955 pub(crate) fn as_module(&self) -> Option<&Module> {
958 match self.kind {
959 ItemKind::Module(ref module) => Some(module),
960 _ => None,
961 }
962 }
963
964 pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> {
967 match self.kind {
968 ItemKind::Module(ref mut module) => Some(module),
969 _ => None,
970 }
971 }
972
973 fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
975 let item = self.id.into_resolver().through_type_refs().resolve(ctx);
978 let ItemKind::Type(ref type_) = *item.kind() else {
979 return false;
980 };
981
982 match *type_.kind() {
983 TypeKind::Enum(ref enum_) => {
984 enum_.computed_enum_variation(ctx, self) ==
985 EnumVariation::ModuleConsts
986 }
987 TypeKind::Alias(inner_id) => {
988 let inner_item = ctx.resolve_item(inner_id);
991 let name = item.canonical_name(ctx);
992
993 if inner_item.canonical_name(ctx) == name {
994 inner_item.is_constified_enum_module(ctx)
995 } else {
996 false
997 }
998 }
999 _ => false,
1000 }
1001 }
1002
1003 pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
1005 let cc = &ctx.options().codegen_config;
1006 match *self.kind() {
1007 ItemKind::Module(..) => true,
1008 ItemKind::Var(_) => cc.vars(),
1009 ItemKind::Type(_) => cc.types(),
1010 ItemKind::Function(ref f) => match f.kind() {
1011 FunctionKind::Function => cc.functions(),
1012 FunctionKind::Method(MethodKind::Constructor) => {
1013 cc.constructors()
1014 }
1015 FunctionKind::Method(MethodKind::Destructor) |
1016 FunctionKind::Method(MethodKind::VirtualDestructor {
1017 ..
1018 }) => cc.destructors(),
1019 FunctionKind::Method(MethodKind::Static) |
1020 FunctionKind::Method(MethodKind::Normal) |
1021 FunctionKind::Method(MethodKind::Virtual { .. }) => {
1022 cc.methods()
1023 }
1024 },
1025 }
1026 }
1027
1028 pub(crate) fn path_for_allowlisting(
1031 &self,
1032 ctx: &BindgenContext,
1033 ) -> &Vec<String> {
1034 self.path_for_allowlisting
1035 .get_or_init(|| self.compute_path(ctx, UserMangled::No))
1036 }
1037
1038 fn compute_path(
1039 &self,
1040 ctx: &BindgenContext,
1041 mangled: UserMangled,
1042 ) -> Vec<String> {
1043 if let Some(path) = self.annotations().use_instead_of() {
1044 let mut ret =
1045 vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
1046 ret.extend_from_slice(path);
1047 return ret;
1048 }
1049
1050 let target = ctx.resolve_item(self.name_target(ctx));
1051 let mut path: Vec<_> = target
1052 .ancestors(ctx)
1053 .chain(iter::once(ctx.root_module().into()))
1054 .map(|id| ctx.resolve_item(id))
1055 .filter(|item| {
1056 item.id() == target.id() ||
1057 item.as_module().is_some_and(|module| {
1058 !module.is_inline() ||
1059 ctx.options().conservative_inline_namespaces
1060 })
1061 })
1062 .map(|item| {
1063 ctx.resolve_item(item.name_target(ctx))
1064 .name(ctx)
1065 .within_namespaces()
1066 .user_mangled(mangled)
1067 .get()
1068 })
1069 .collect();
1070 path.reverse();
1071 path
1072 }
1073
1074 fn c_naming_prefix(&self) -> Option<&str> {
1076 let ItemKind::Type(ref ty) = self.kind else {
1077 return None;
1078 };
1079
1080 Some(match ty.kind() {
1081 TypeKind::Comp(ref ci) => match ci.kind() {
1082 CompKind::Struct => "struct",
1083 CompKind::Union => "union",
1084 },
1085 TypeKind::Enum(..) => "enum",
1086 _ => return None,
1087 })
1088 }
1089
1090 pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
1092 self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
1093 }
1094}
1095
1096impl<T> IsOpaque for T
1097where
1098 T: Copy + Into<ItemId>,
1099{
1100 type Extra = ();
1101
1102 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1103 debug_assert!(
1104 ctx.in_codegen_phase(),
1105 "You're not supposed to call this yet"
1106 );
1107 ctx.resolve_item((*self).into()).is_opaque(ctx, &())
1108 }
1109}
1110
1111impl IsOpaque for Item {
1112 type Extra = ();
1113
1114 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1115 debug_assert!(
1116 ctx.in_codegen_phase(),
1117 "You're not supposed to call this yet"
1118 );
1119 self.annotations.opaque() ||
1120 self.as_type().is_some_and(|ty| ty.is_opaque(ctx, self)) ||
1121 ctx.opaque_by_name(self.path_for_allowlisting(ctx))
1122 }
1123}
1124
1125impl<T> HasVtable for T
1126where
1127 T: Copy + Into<ItemId>,
1128{
1129 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1130 let id: ItemId = (*self).into();
1131 id.as_type_id(ctx).is_some_and(|id| {
1132 !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No)
1133 })
1134 }
1135
1136 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1137 let id: ItemId = (*self).into();
1138 id.as_type_id(ctx).is_some_and(|id| {
1139 matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable)
1140 })
1141 }
1142}
1143
1144impl HasVtable for Item {
1145 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1146 self.id().has_vtable(ctx)
1147 }
1148
1149 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1150 self.id().has_vtable_ptr(ctx)
1151 }
1152}
1153
1154impl<T> Sizedness for T
1155where
1156 T: Copy + Into<ItemId>,
1157{
1158 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1159 let id: ItemId = (*self).into();
1160 id.as_type_id(ctx)
1161 .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id))
1162 }
1163}
1164
1165impl Sizedness for Item {
1166 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1167 self.id().sizedness(ctx)
1168 }
1169}
1170
1171impl<T> HasTypeParamInArray for T
1172where
1173 T: Copy + Into<ItemId>,
1174{
1175 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1176 debug_assert!(
1177 ctx.in_codegen_phase(),
1178 "You're not supposed to call this yet"
1179 );
1180 ctx.lookup_has_type_param_in_array(*self)
1181 }
1182}
1183
1184impl HasTypeParamInArray for Item {
1185 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1186 debug_assert!(
1187 ctx.in_codegen_phase(),
1188 "You're not supposed to call this yet"
1189 );
1190 ctx.lookup_has_type_param_in_array(self.id())
1191 }
1192}
1193
1194pub(crate) type ItemSet = BTreeSet<ItemId>;
1196
1197impl DotAttributes for Item {
1198 fn dot_attributes<W>(
1199 &self,
1200 ctx: &BindgenContext,
1201 out: &mut W,
1202 ) -> io::Result<()>
1203 where
1204 W: io::Write,
1205 {
1206 writeln!(
1207 out,
1208 "<tr><td>{:?}</td></tr>
1209 <tr><td>name</td><td>{}</td></tr>",
1210 self.id,
1211 self.name(ctx).get()
1212 )?;
1213
1214 if self.is_opaque(ctx, &()) {
1215 writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
1216 }
1217
1218 self.kind.dot_attributes(ctx, out)
1219 }
1220}
1221
1222impl<T> TemplateParameters for T
1223where
1224 T: Copy + Into<ItemId>,
1225{
1226 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1227 ctx.resolve_item_fallible(*self)
1228 .map_or(vec![], |item| item.self_template_params(ctx))
1229 }
1230}
1231
1232impl TemplateParameters for Item {
1233 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1234 self.kind.self_template_params(ctx)
1235 }
1236}
1237
1238impl TemplateParameters for ItemKind {
1239 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1240 match *self {
1241 ItemKind::Type(ref ty) => ty.self_template_params(ctx),
1242 ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => {
1246 vec![]
1247 }
1248 }
1249 }
1250}
1251
1252fn visit_child(
1254 cur: clang::Cursor,
1255 id: ItemId,
1256 ty: &clang::Type,
1257 parent_id: Option<ItemId>,
1258 ctx: &mut BindgenContext,
1259 result: &mut Result<TypeId, ParseError>,
1260) -> clang_sys::CXChildVisitResult {
1261 use clang_sys::*;
1262 if result.is_ok() {
1263 return CXChildVisit_Break;
1264 }
1265
1266 *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
1267
1268 match *result {
1269 Ok(..) => CXChildVisit_Break,
1270 Err(ParseError::Recurse) => {
1271 cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result));
1272 CXChildVisit_Continue
1273 }
1274 Err(ParseError::Continue) => CXChildVisit_Continue,
1275 }
1276}
1277
1278impl Item {
1279 pub(crate) fn builtin_type(
1281 kind: TypeKind,
1282 is_const: bool,
1283 ctx: &mut BindgenContext,
1284 ) -> TypeId {
1285 match kind {
1287 TypeKind::Void |
1288 TypeKind::Int(..) |
1289 TypeKind::Pointer(..) |
1290 TypeKind::Float(..) => {}
1291 _ => panic!("Unsupported builtin type"),
1292 }
1293
1294 let ty = Type::new(None, None, kind, is_const);
1295 let id = ctx.next_item_id();
1296 let module = ctx.root_module().into();
1297 ctx.add_item(
1298 Item::new(id, None, None, module, ItemKind::Type(ty), None),
1299 None,
1300 None,
1301 );
1302 id.as_type_id_unchecked()
1303 }
1304
1305 pub(crate) fn parse(
1307 cursor: clang::Cursor,
1308 parent_id: Option<ItemId>,
1309 ctx: &mut BindgenContext,
1310 ) -> Result<ItemId, ParseError> {
1311 use crate::ir::var::Var;
1312 use clang_sys::*;
1313
1314 if !cursor.is_valid() {
1315 return Err(ParseError::Continue);
1316 }
1317
1318 let comment = cursor.raw_comment();
1319 let annotations = Annotations::new(&cursor);
1320
1321 let current_module = ctx.current_module().into();
1322 let relevant_parent_id = parent_id.unwrap_or(current_module);
1323
1324 #[allow(clippy::missing_docs_in_private_items)]
1325 macro_rules! try_parse {
1326 ($what:ident) => {
1327 match $what::parse(cursor, ctx) {
1328 Ok(ParseResult::New(item, declaration)) => {
1329 let id = ctx.next_item_id();
1330
1331 ctx.add_item(
1332 Item::new(
1333 id,
1334 comment,
1335 annotations,
1336 relevant_parent_id,
1337 ItemKind::$what(item),
1338 Some(cursor.location()),
1339 ),
1340 declaration,
1341 Some(cursor),
1342 );
1343 return Ok(id);
1344 }
1345 Ok(ParseResult::AlreadyResolved(id)) => {
1346 return Ok(id);
1347 }
1348 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1349 Err(ParseError::Continue) => {}
1350 }
1351 };
1352 }
1353
1354 try_parse!(Module);
1355
1356 try_parse!(Function);
1364 try_parse!(Var);
1365
1366 {
1369 let definition = cursor.definition();
1370 let applicable_cursor = definition.unwrap_or(cursor);
1371
1372 let relevant_parent_id = match definition {
1373 Some(definition) => {
1374 if definition != cursor {
1375 ctx.add_semantic_parent(definition, relevant_parent_id);
1376 return Ok(Item::from_ty_or_ref(
1377 applicable_cursor.cur_type(),
1378 cursor,
1379 parent_id,
1380 ctx,
1381 )
1382 .into());
1383 }
1384 ctx.known_semantic_parent(definition)
1385 .or(parent_id)
1386 .unwrap_or_else(|| ctx.current_module().into())
1387 }
1388 None => relevant_parent_id,
1389 };
1390
1391 match Item::from_ty(
1392 &applicable_cursor.cur_type(),
1393 applicable_cursor,
1394 Some(relevant_parent_id),
1395 ctx,
1396 ) {
1397 Ok(ty) => return Ok(ty.into()),
1398 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1399 Err(ParseError::Continue) => {}
1400 }
1401 }
1402
1403 match cursor.kind() {
1404 CXCursor_LinkageSpec | CXCursor_UnexposedDecl => {
1407 Err(ParseError::Recurse)
1408 }
1409
1410 CXCursor_MacroDefinition |
1413 CXCursor_MacroExpansion |
1414 CXCursor_UsingDeclaration |
1415 CXCursor_UsingDirective |
1416 CXCursor_StaticAssert |
1417 CXCursor_FunctionTemplate => {
1418 debug!("Unhandled cursor kind {:?}: {cursor:?}", cursor.kind(),);
1419 Err(ParseError::Continue)
1420 }
1421
1422 CXCursor_InclusionDirective => {
1423 let file = cursor.get_included_file_name();
1424 match file {
1425 None => {
1426 warn!("Inclusion of a nameless file in {cursor:?}");
1427 }
1428 Some(included_file) => {
1429 for cb in &ctx.options().parse_callbacks {
1430 cb.include_file(&included_file);
1431 }
1432
1433 ctx.add_dep(included_file.into_boxed_str());
1434 }
1435 }
1436 Err(ParseError::Continue)
1437 }
1438
1439 _ => {
1440 let spelling = cursor.spelling();
1442 if !spelling.starts_with("operator") {
1443 warn!(
1444 "Unhandled cursor kind {:?}: {cursor:?}",
1445 cursor.kind(),
1446 );
1447 }
1448 Err(ParseError::Continue)
1449 }
1450 }
1451 }
1452
1453 pub(crate) fn from_ty_or_ref(
1456 ty: clang::Type,
1457 location: clang::Cursor,
1458 parent_id: Option<ItemId>,
1459 ctx: &mut BindgenContext,
1460 ) -> TypeId {
1461 let id = ctx.next_item_id();
1462 Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
1463 }
1464
1465 pub(crate) fn from_ty_or_ref_with_id(
1476 potential_id: ItemId,
1477 ty: clang::Type,
1478 location: clang::Cursor,
1479 parent_id: Option<ItemId>,
1480 ctx: &mut BindgenContext,
1481 ) -> TypeId {
1482 debug!("from_ty_or_ref_with_id: {potential_id:?} {ty:?}, {location:?}, {parent_id:?}");
1483
1484 if ctx.collected_typerefs() {
1485 debug!("refs already collected, resolving directly");
1486 return Item::from_ty_with_id(
1487 potential_id,
1488 &ty,
1489 location,
1490 parent_id,
1491 ctx,
1492 )
1493 .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx));
1494 }
1495
1496 if let Some(ty) = ctx.builtin_or_resolved_ty(
1497 potential_id,
1498 parent_id,
1499 &ty,
1500 Some(location),
1501 ) {
1502 debug!("{ty:?} already resolved: {location:?}");
1503 return ty;
1504 }
1505
1506 debug!("New unresolved type reference: {ty:?}, {location:?}");
1507
1508 let is_const = ty.is_const();
1509 let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
1510 let current_module = ctx.current_module();
1511
1512 ctx.add_item(
1513 Item::new(
1514 potential_id,
1515 None,
1516 None,
1517 parent_id.unwrap_or_else(|| current_module.into()),
1518 ItemKind::Type(Type::new(None, None, kind, is_const)),
1519 Some(location.location()),
1520 ),
1521 None,
1522 None,
1523 );
1524 potential_id.as_type_id_unchecked()
1525 }
1526
1527 pub(crate) fn from_ty(
1529 ty: &clang::Type,
1530 location: clang::Cursor,
1531 parent_id: Option<ItemId>,
1532 ctx: &mut BindgenContext,
1533 ) -> Result<TypeId, ParseError> {
1534 let id = ctx.next_item_id();
1535 Item::from_ty_with_id(id, ty, location, parent_id, ctx)
1536 }
1537
1538 pub(crate) fn from_ty_with_id(
1547 id: ItemId,
1548 ty: &clang::Type,
1549 location: clang::Cursor,
1550 parent_id: Option<ItemId>,
1551 ctx: &mut BindgenContext,
1552 ) -> Result<TypeId, ParseError> {
1553 use clang_sys::*;
1554
1555 debug!(
1556 "Item::from_ty_with_id: {id:?}\n\
1557 \tty = {ty:?},\n\
1558 \tlocation = {location:?}",
1559 );
1560
1561 if ty.kind() == CXType_Unexposed ||
1562 location.cur_type().kind() == CXType_Unexposed
1563 {
1564 if ty.is_associated_type() ||
1565 location.cur_type().is_associated_type()
1566 {
1567 return Ok(Item::new_opaque_type(id, ty, ctx));
1568 }
1569
1570 if let Some(param_id) = Item::type_param(None, location, ctx) {
1571 return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
1572 }
1573 }
1574
1575 if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
1581 if FunctionKind::from_cursor(parent).is_some() {
1582 debug!("Skipping type declared inside function: {ty:?}");
1583 return Ok(Item::new_opaque_type(id, ty, ctx));
1584 }
1585 }
1586
1587 let decl = {
1588 let canonical_def = ty.canonical_type().declaration().definition();
1589 canonical_def.unwrap_or_else(|| ty.declaration())
1590 };
1591
1592 let comment = location
1593 .raw_comment()
1594 .or_else(|| decl.raw_comment())
1595 .or_else(|| location.raw_comment());
1596
1597 let annotations =
1598 Annotations::new(&decl).or_else(|| Annotations::new(&location));
1599
1600 if let Some(ref annotations) = annotations {
1601 if let Some(replaced) = annotations.use_instead_of() {
1602 ctx.replace(replaced, id);
1603 }
1604 }
1605
1606 if let Some(ty) =
1607 ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location))
1608 {
1609 return Ok(ty);
1610 }
1611
1612 let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
1614 let declaration_to_look_for = if valid_decl {
1615 decl.canonical()
1616 } else if location.kind() == CXCursor_ClassTemplate {
1617 valid_decl = true;
1618 location
1619 } else {
1620 decl
1621 };
1622
1623 if valid_decl {
1624 if let Some(partial) = ctx
1625 .currently_parsed_types()
1626 .iter()
1627 .find(|ty| *ty.decl() == declaration_to_look_for)
1628 {
1629 debug!("Avoiding recursion parsing type: {ty:?}");
1630 return Ok(partial.id().as_type_id_unchecked());
1632 }
1633 }
1634
1635 let current_module = ctx.current_module().into();
1636 let partial_ty = PartialType::new(declaration_to_look_for, id);
1637 if valid_decl {
1638 ctx.begin_parsing(partial_ty);
1639 }
1640
1641 let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
1642 let relevant_parent_id = parent_id.unwrap_or(current_module);
1643 let ret = match result {
1644 Ok(ParseResult::AlreadyResolved(ty)) => {
1645 Ok(ty.as_type_id_unchecked())
1646 }
1647 Ok(ParseResult::New(item, declaration)) => {
1648 ctx.add_item(
1649 Item::new(
1650 id,
1651 comment,
1652 annotations,
1653 relevant_parent_id,
1654 ItemKind::Type(item),
1655 Some(location.location()),
1656 ),
1657 declaration,
1658 Some(location),
1659 );
1660 Ok(id.as_type_id_unchecked())
1661 }
1662 Err(ParseError::Continue) => Err(ParseError::Continue),
1663 Err(ParseError::Recurse) => {
1664 debug!("Item::from_ty recursing in the ast");
1665 let mut result = Err(ParseError::Recurse);
1666
1667 if valid_decl {
1673 let finished = ctx.finish_parsing();
1674 assert_eq!(*finished.decl(), declaration_to_look_for);
1675 }
1676
1677 location.visit(|cur| {
1678 visit_child(cur, id, ty, parent_id, ctx, &mut result)
1679 });
1680
1681 if valid_decl {
1682 let partial_ty =
1683 PartialType::new(declaration_to_look_for, id);
1684 ctx.begin_parsing(partial_ty);
1685 }
1686
1687 if let Err(ParseError::Recurse) = result {
1693 warn!(
1694 "Unknown type, assuming named template type: \
1695 id = {:?}; spelling = {}",
1696 id,
1697 ty.spelling()
1698 );
1699 Item::type_param(Some(id), location, ctx)
1700 .ok_or(ParseError::Recurse)
1701 } else {
1702 result
1703 }
1704 }
1705 };
1706
1707 if valid_decl {
1708 let partial_ty = ctx.finish_parsing();
1709 assert_eq!(*partial_ty.decl(), declaration_to_look_for);
1710 }
1711
1712 ret
1713 }
1714
1715 pub(crate) fn type_param(
1718 with_id: Option<ItemId>,
1719 location: clang::Cursor,
1720 ctx: &mut BindgenContext,
1721 ) -> Option<TypeId> {
1722 let ty = location.cur_type();
1723
1724 debug!(
1725 "Item::type_param:\n\
1726 \twith_id = {:?},\n\
1727 \tty = {} {:?},\n\
1728 \tlocation: {:?}",
1729 with_id,
1730 ty.spelling(),
1731 ty,
1732 location
1733 );
1734
1735 if ty.kind() != clang_sys::CXType_Unexposed {
1736 return None;
1741 }
1742
1743 let ty_spelling = ty.spelling();
1744
1745 fn is_template_with_spelling(
1791 refd: &clang::Cursor,
1792 spelling: &str,
1793 ) -> bool {
1794 static ANON_TYPE_PARAM_RE: OnceLock<regex::Regex> = OnceLock::new();
1795 let anon_type_param_re = ANON_TYPE_PARAM_RE.get_or_init(|| {
1796 regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap()
1797 });
1798
1799 if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter {
1800 return false;
1801 }
1802
1803 let refd_spelling = refd.spelling();
1804 refd_spelling == spelling ||
1805 (refd_spelling.is_empty() && anon_type_param_re.is_match(spelling.as_ref()))
1807 }
1808
1809 let definition = if is_template_with_spelling(&location, &ty_spelling) {
1810 location
1812 } else if location.kind() == clang_sys::CXCursor_TypeRef {
1813 match location.referenced() {
1815 Some(refd)
1816 if is_template_with_spelling(&refd, &ty_spelling) =>
1817 {
1818 refd
1819 }
1820 _ => return None,
1821 }
1822 } else {
1823 let mut definition = None;
1825
1826 location.visit(|child| {
1827 let child_ty = child.cur_type();
1828 if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
1829 child_ty.spelling() == ty_spelling
1830 {
1831 match child.referenced() {
1832 Some(refd)
1833 if is_template_with_spelling(
1834 &refd,
1835 &ty_spelling,
1836 ) =>
1837 {
1838 definition = Some(refd);
1839 return clang_sys::CXChildVisit_Break;
1840 }
1841 _ => {}
1842 }
1843 }
1844
1845 clang_sys::CXChildVisit_Continue
1846 });
1847
1848 definition?
1849 };
1850 assert!(is_template_with_spelling(&definition, &ty_spelling));
1851
1852 let parent = ctx.root_module().into();
1857
1858 if let Some(id) = ctx.get_type_param(&definition) {
1859 if let Some(with_id) = with_id {
1860 return Some(ctx.build_ty_wrapper(
1861 with_id,
1862 id,
1863 Some(parent),
1864 &ty,
1865 ));
1866 } else {
1867 return Some(id);
1868 }
1869 }
1870
1871 let name = ty_spelling.replace("const ", "").replace('.', "");
1874
1875 let id = with_id.unwrap_or_else(|| ctx.next_item_id());
1876 let item = Item::new(
1877 id,
1878 None,
1879 None,
1880 parent,
1881 ItemKind::Type(Type::named(name)),
1882 Some(location.location()),
1883 );
1884 ctx.add_type_param(item, definition);
1885 Some(id.as_type_id_unchecked())
1886 }
1887}
1888
1889impl ItemCanonicalName for Item {
1890 fn canonical_name(&self, ctx: &BindgenContext) -> String {
1891 debug_assert!(
1892 ctx.in_codegen_phase(),
1893 "You're not supposed to call this yet"
1894 );
1895 self.canonical_name
1896 .get_or_init(|| {
1897 let in_namespace = ctx.options().enable_cxx_namespaces ||
1898 ctx.options().disable_name_namespacing;
1899
1900 if in_namespace {
1901 self.name(ctx).within_namespaces().get()
1902 } else {
1903 self.name(ctx).get()
1904 }
1905 })
1906 .clone()
1907 }
1908}
1909
1910impl ItemCanonicalPath for Item {
1911 fn namespace_aware_canonical_path(
1912 &self,
1913 ctx: &BindgenContext,
1914 ) -> Vec<String> {
1915 let mut path = self.canonical_path(ctx);
1916
1917 if ctx.options().disable_name_namespacing {
1921 let split_idx = path.len() - 1;
1923 path = path.split_off(split_idx);
1924 } else if !ctx.options().enable_cxx_namespaces {
1925 path = vec![path[1..].join("_")];
1927 }
1928
1929 if self.is_constified_enum_module(ctx) {
1930 path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
1931 }
1932
1933 path
1934 }
1935
1936 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
1937 self.compute_path(ctx, UserMangled::Yes)
1938 }
1939}
1940
1941#[derive(Copy, Clone, Debug, PartialEq)]
1947enum UserMangled {
1948 No,
1949 Yes,
1950}
1951
1952#[derive(Debug)]
1955pub(crate) struct NameOptions<'a> {
1956 item: &'a Item,
1957 ctx: &'a BindgenContext,
1958 within_namespaces: bool,
1959 user_mangled: UserMangled,
1960}
1961
1962impl<'a> NameOptions<'a> {
1963 pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
1965 NameOptions {
1966 item,
1967 ctx,
1968 within_namespaces: false,
1969 user_mangled: UserMangled::Yes,
1970 }
1971 }
1972
1973 pub(crate) fn within_namespaces(&mut self) -> &mut Self {
1976 self.within_namespaces = true;
1977 self
1978 }
1979
1980 fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self {
1981 self.user_mangled = user_mangled;
1982 self
1983 }
1984
1985 pub(crate) fn get(&self) -> String {
1987 self.item.real_canonical_name(self.ctx, self)
1988 }
1989}