1 //! Bindgen's core intermediate representation type.
2
3 use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
4 use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
5 use super::annotations::Annotations;
6 use super::comp::{CompKind, MethodKind};
7 use super::context::{BindgenContext, ItemId, PartialType, TypeId};
8 use super::derive::{
9 CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
10 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
11 };
12 use super::dot::DotAttributes;
13 use super::function::{Function, FunctionKind};
14 use super::item_kind::ItemKind;
15 use super::layout::Opaque;
16 use super::module::Module;
17 use super::template::{AsTemplateParam, TemplateParameters};
18 use super::traversal::{EdgeKind, Trace, Tracer};
19 use super::ty::{Type, TypeKind};
20 use crate::clang;
21 use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
22
23 use lazycell::LazyCell;
24
25 use std::cell::Cell;
26 use std::collections::BTreeSet;
27 use std::fmt::Write;
28 use std::io;
29 use std::iter;
30
31 /// A trait to get the canonical name from an item.
32 ///
33 /// This is the trait that will eventually isolate all the logic related to name
34 /// mangling and that kind of stuff.
35 ///
36 /// This assumes no nested paths, at some point I'll have to make it a more
37 /// complex thing.
38 ///
39 /// This name is required to be safe for Rust, that is, is not expected to
40 /// return any rust keyword from here.
41 pub(crate) trait ItemCanonicalName {
42 /// Get the canonical name for this item.
canonical_name(&self, ctx: &BindgenContext) -> String43 fn canonical_name(&self, ctx: &BindgenContext) -> String;
44 }
45
46 /// The same, but specifies the path that needs to be followed to reach an item.
47 ///
48 /// To contrast with canonical_name, here's an example:
49 ///
50 /// ```c++
51 /// namespace foo {
52 /// const BAR = 3;
53 /// }
54 /// ```
55 ///
56 /// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical
57 /// name is just `"BAR"`.
58 pub(crate) trait ItemCanonicalPath {
59 /// Get the namespace-aware canonical path for this item. This means that if
60 /// namespaces are disabled, you'll get a single item, and otherwise you get
61 /// the whole path.
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>62 fn namespace_aware_canonical_path(
63 &self,
64 ctx: &BindgenContext,
65 ) -> Vec<String>;
66
67 /// Get the canonical path for this item.
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>68 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
69 }
70
71 /// A trait for determining if some IR thing is opaque or not.
72 pub(crate) trait IsOpaque {
73 /// Extra context the IR thing needs to determine if it is opaque or not.
74 type Extra;
75
76 /// Returns `true` if the thing is opaque, and `false` otherwise.
77 ///
78 /// May only be called when `ctx` is in the codegen phase.
is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool79 fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
80 }
81
82 /// A trait for determining if some IR thing has type parameter in array or not.
83 pub(crate) trait HasTypeParamInArray {
84 /// Returns `true` if the thing has Array, and `false` otherwise.
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool85 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool;
86 }
87
88 /// A trait for determining if some IR thing has float or not.
89 pub(crate) trait HasFloat {
90 /// Returns `true` if the thing has float, and `false` otherwise.
has_float(&self, ctx: &BindgenContext) -> bool91 fn has_float(&self, ctx: &BindgenContext) -> bool;
92 }
93
94 /// A trait for iterating over an item and its parents and up its ancestor chain
95 /// up to (but not including) the implicit root module.
96 pub(crate) trait ItemAncestors {
97 /// Get an iterable over this item's ancestors.
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>98 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
99 }
100
101 #[cfg(feature = "__testing_only_extra_assertions")]
102 type DebugOnlyItemSet = ItemSet;
103
104 #[cfg(not(feature = "__testing_only_extra_assertions"))]
105 struct DebugOnlyItemSet;
106
107 #[cfg(not(feature = "__testing_only_extra_assertions"))]
108 impl DebugOnlyItemSet {
new() -> Self109 fn new() -> Self {
110 DebugOnlyItemSet
111 }
112
contains(&self, _id: &ItemId) -> bool113 fn contains(&self, _id: &ItemId) -> bool {
114 false
115 }
116
insert(&mut self, _id: ItemId)117 fn insert(&mut self, _id: ItemId) {}
118 }
119
120 /// An iterator over an item and its ancestors.
121 pub(crate) struct ItemAncestorsIter<'a> {
122 item: ItemId,
123 ctx: &'a BindgenContext,
124 seen: DebugOnlyItemSet,
125 }
126
127 impl<'a> ItemAncestorsIter<'a> {
new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self128 fn new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self {
129 ItemAncestorsIter {
130 item: id.into(),
131 ctx,
132 seen: DebugOnlyItemSet::new(),
133 }
134 }
135 }
136
137 impl<'a> Iterator for ItemAncestorsIter<'a> {
138 type Item = ItemId;
139
next(&mut self) -> Option<Self::Item>140 fn next(&mut self) -> Option<Self::Item> {
141 let item = self.ctx.resolve_item(self.item);
142
143 if item.parent_id() == self.item {
144 None
145 } else {
146 self.item = item.parent_id();
147
148 extra_assert!(!self.seen.contains(&item.id()));
149 self.seen.insert(item.id());
150
151 Some(item.id())
152 }
153 }
154 }
155
156 impl<T> AsTemplateParam for T
157 where
158 T: Copy + Into<ItemId>,
159 {
160 type Extra = ();
161
as_template_param( &self, ctx: &BindgenContext, _: &(), ) -> Option<TypeId>162 fn as_template_param(
163 &self,
164 ctx: &BindgenContext,
165 _: &(),
166 ) -> Option<TypeId> {
167 ctx.resolve_item((*self).into()).as_template_param(ctx, &())
168 }
169 }
170
171 impl AsTemplateParam for Item {
172 type Extra = ();
173
as_template_param( &self, ctx: &BindgenContext, _: &(), ) -> Option<TypeId>174 fn as_template_param(
175 &self,
176 ctx: &BindgenContext,
177 _: &(),
178 ) -> Option<TypeId> {
179 self.kind.as_template_param(ctx, self)
180 }
181 }
182
183 impl AsTemplateParam for ItemKind {
184 type Extra = Item;
185
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>186 fn as_template_param(
187 &self,
188 ctx: &BindgenContext,
189 item: &Item,
190 ) -> Option<TypeId> {
191 match *self {
192 ItemKind::Type(ref ty) => ty.as_template_param(ctx, item),
193 ItemKind::Module(..) |
194 ItemKind::Function(..) |
195 ItemKind::Var(..) => None,
196 }
197 }
198 }
199
200 impl<T> ItemCanonicalName for T
201 where
202 T: Copy + Into<ItemId>,
203 {
canonical_name(&self, ctx: &BindgenContext) -> String204 fn canonical_name(&self, ctx: &BindgenContext) -> String {
205 debug_assert!(
206 ctx.in_codegen_phase(),
207 "You're not supposed to call this yet"
208 );
209 ctx.resolve_item(*self).canonical_name(ctx)
210 }
211 }
212
213 impl<T> ItemCanonicalPath for T
214 where
215 T: Copy + Into<ItemId>,
216 {
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>217 fn namespace_aware_canonical_path(
218 &self,
219 ctx: &BindgenContext,
220 ) -> Vec<String> {
221 debug_assert!(
222 ctx.in_codegen_phase(),
223 "You're not supposed to call this yet"
224 );
225 ctx.resolve_item(*self).namespace_aware_canonical_path(ctx)
226 }
227
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>228 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
229 debug_assert!(
230 ctx.in_codegen_phase(),
231 "You're not supposed to call this yet"
232 );
233 ctx.resolve_item(*self).canonical_path(ctx)
234 }
235 }
236
237 impl<T> ItemAncestors for T
238 where
239 T: Copy + Into<ItemId>,
240 {
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>241 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
242 ItemAncestorsIter::new(ctx, *self)
243 }
244 }
245
246 impl ItemAncestors for Item {
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>247 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
248 self.id().ancestors(ctx)
249 }
250 }
251
252 impl<Id> Trace for Id
253 where
254 Id: Copy + Into<ItemId>,
255 {
256 type Extra = ();
257
trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &()) where T: Tracer,258 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &())
259 where
260 T: Tracer,
261 {
262 ctx.resolve_item(*self).trace(ctx, tracer, extra);
263 }
264 }
265
266 impl Trace for Item {
267 type Extra = ();
268
trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &()) where T: Tracer,269 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &())
270 where
271 T: Tracer,
272 {
273 // Even if this item is blocklisted/hidden, we want to trace it. It is
274 // traversal iterators' consumers' responsibility to filter items as
275 // needed. Generally, this filtering happens in the implementation of
276 // `Iterator` for `allowlistedItems`. Fully tracing blocklisted items is
277 // necessary for things like the template parameter usage analysis to
278 // function correctly.
279
280 match *self.kind() {
281 ItemKind::Type(ref ty) => {
282 // There are some types, like resolved type references, where we
283 // don't want to stop collecting types even though they may be
284 // opaque.
285 if ty.should_be_traced_unconditionally() ||
286 !self.is_opaque(ctx, &())
287 {
288 ty.trace(ctx, tracer, self);
289 }
290 }
291 ItemKind::Function(ref fun) => {
292 // Just the same way, it has not real meaning for a function to
293 // be opaque, so we trace across it.
294 tracer.visit(fun.signature().into());
295 }
296 ItemKind::Var(ref var) => {
297 tracer.visit_kind(var.ty().into(), EdgeKind::VarType);
298 }
299 ItemKind::Module(_) => {
300 // Module -> children edges are "weak", and we do not want to
301 // trace them. If we did, then allowlisting wouldn't work as
302 // expected: everything in every module would end up
303 // allowlisted.
304 //
305 // TODO: make a new edge kind for module -> children edges and
306 // filter them during allowlisting traversals.
307 }
308 }
309 }
310 }
311
312 impl CanDeriveDebug for Item {
can_derive_debug(&self, ctx: &BindgenContext) -> bool313 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
314 self.id().can_derive_debug(ctx)
315 }
316 }
317
318 impl CanDeriveDefault for Item {
can_derive_default(&self, ctx: &BindgenContext) -> bool319 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
320 self.id().can_derive_default(ctx)
321 }
322 }
323
324 impl CanDeriveCopy for Item {
can_derive_copy(&self, ctx: &BindgenContext) -> bool325 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
326 self.id().can_derive_copy(ctx)
327 }
328 }
329
330 impl CanDeriveHash for Item {
can_derive_hash(&self, ctx: &BindgenContext) -> bool331 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
332 self.id().can_derive_hash(ctx)
333 }
334 }
335
336 impl CanDerivePartialOrd for Item {
can_derive_partialord(&self, ctx: &BindgenContext) -> bool337 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
338 self.id().can_derive_partialord(ctx)
339 }
340 }
341
342 impl CanDerivePartialEq for Item {
can_derive_partialeq(&self, ctx: &BindgenContext) -> bool343 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
344 self.id().can_derive_partialeq(ctx)
345 }
346 }
347
348 impl CanDeriveEq for Item {
can_derive_eq(&self, ctx: &BindgenContext) -> bool349 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
350 self.id().can_derive_eq(ctx)
351 }
352 }
353
354 impl CanDeriveOrd for Item {
can_derive_ord(&self, ctx: &BindgenContext) -> bool355 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
356 self.id().can_derive_ord(ctx)
357 }
358 }
359
360 /// An item is the base of the bindgen representation, it can be either a
361 /// module, a type, a function, or a variable (see `ItemKind` for more
362 /// information).
363 ///
364 /// Items refer to each other by `ItemId`. Every item has its parent's
365 /// ID. Depending on the kind of item this is, it may also refer to other items,
366 /// such as a compound type item referring to other types. Collectively, these
367 /// references form a graph.
368 ///
369 /// The entry-point to this graph is the "root module": a meta-item used to hold
370 /// all top-level items.
371 ///
372 /// An item may have a comment, and annotations (see the `annotations` module).
373 ///
374 /// Note that even though we parse all the types of annotations in comments, not
375 /// all of them apply to every item. Those rules are described in the
376 /// `annotations` module.
377 #[derive(Debug)]
378 pub(crate) struct Item {
379 /// This item's ID.
380 id: ItemId,
381
382 /// The item's local ID, unique only amongst its siblings. Only used for
383 /// anonymous items.
384 ///
385 /// Lazily initialized in local_id().
386 ///
387 /// Note that only structs, unions, and enums get a local type ID. In any
388 /// case this is an implementation detail.
389 local_id: LazyCell<usize>,
390
391 /// The next local ID to use for a child or template instantiation.
392 next_child_local_id: Cell<usize>,
393
394 /// A cached copy of the canonical name, as returned by `canonical_name`.
395 ///
396 /// This is a fairly used operation during codegen so this makes bindgen
397 /// considerably faster in those cases.
398 canonical_name: LazyCell<String>,
399
400 /// The path to use for allowlisting and other name-based checks, as
401 /// returned by `path_for_allowlisting`, lazily constructed.
402 path_for_allowlisting: LazyCell<Vec<String>>,
403
404 /// A doc comment over the item, if any.
405 comment: Option<String>,
406 /// Annotations extracted from the doc comment, or the default ones
407 /// otherwise.
408 annotations: Annotations,
409 /// An item's parent ID. This will most likely be a class where this item
410 /// was declared, or a module, etc.
411 ///
412 /// All the items have a parent, except the root module, in which case the
413 /// parent ID is its own ID.
414 parent_id: ItemId,
415 /// The item kind.
416 kind: ItemKind,
417 /// The source location of the item.
418 location: Option<clang::SourceLocation>,
419 }
420
421 impl AsRef<ItemId> for Item {
as_ref(&self) -> &ItemId422 fn as_ref(&self) -> &ItemId {
423 &self.id
424 }
425 }
426
427 impl Item {
428 /// Construct a new `Item`.
new( id: ItemId, comment: Option<String>, annotations: Option<Annotations>, parent_id: ItemId, kind: ItemKind, location: Option<clang::SourceLocation>, ) -> Self429 pub(crate) fn new(
430 id: ItemId,
431 comment: Option<String>,
432 annotations: Option<Annotations>,
433 parent_id: ItemId,
434 kind: ItemKind,
435 location: Option<clang::SourceLocation>,
436 ) -> Self {
437 debug_assert!(id != parent_id || kind.is_module());
438 Item {
439 id,
440 local_id: LazyCell::new(),
441 next_child_local_id: Cell::new(1),
442 canonical_name: LazyCell::new(),
443 path_for_allowlisting: LazyCell::new(),
444 parent_id,
445 comment,
446 annotations: annotations.unwrap_or_default(),
447 kind,
448 location,
449 }
450 }
451
452 /// Construct a new opaque item type.
new_opaque_type( with_id: ItemId, ty: &clang::Type, ctx: &mut BindgenContext, ) -> TypeId453 pub(crate) fn new_opaque_type(
454 with_id: ItemId,
455 ty: &clang::Type,
456 ctx: &mut BindgenContext,
457 ) -> TypeId {
458 let location = ty.declaration().location();
459 let ty = Opaque::from_clang_ty(ty, ctx);
460 let kind = ItemKind::Type(ty);
461 let parent = ctx.root_module().into();
462 ctx.add_item(
463 Item::new(with_id, None, None, parent, kind, Some(location)),
464 None,
465 None,
466 );
467 with_id.as_type_id_unchecked()
468 }
469
470 /// Get this `Item`'s identifier.
id(&self) -> ItemId471 pub(crate) fn id(&self) -> ItemId {
472 self.id
473 }
474
475 /// Get this `Item`'s parent's identifier.
476 ///
477 /// For the root module, the parent's ID is its own ID.
parent_id(&self) -> ItemId478 pub(crate) fn parent_id(&self) -> ItemId {
479 self.parent_id
480 }
481
482 /// Set this item's parent ID.
483 ///
484 /// This is only used so replacements get generated in the proper module.
set_parent_for_replacement<Id: Into<ItemId>>( &mut self, id: Id, )485 pub(crate) fn set_parent_for_replacement<Id: Into<ItemId>>(
486 &mut self,
487 id: Id,
488 ) {
489 self.parent_id = id.into();
490 }
491
492 /// Returns the depth this item is indented to.
493 ///
494 /// FIXME(emilio): This may need fixes for the enums within modules stuff.
codegen_depth(&self, ctx: &BindgenContext) -> usize495 pub(crate) fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
496 if !ctx.options().enable_cxx_namespaces {
497 return 0;
498 }
499
500 self.ancestors(ctx)
501 .filter(|id| {
502 ctx.resolve_item(*id).as_module().map_or(false, |module| {
503 !module.is_inline() ||
504 ctx.options().conservative_inline_namespaces
505 })
506 })
507 .count() +
508 1
509 }
510
511 /// Get this `Item`'s comment, if it has any, already preprocessed and with
512 /// the right indentation.
comment(&self, ctx: &BindgenContext) -> Option<String>513 pub(crate) fn comment(&self, ctx: &BindgenContext) -> Option<String> {
514 if !ctx.options().generate_comments {
515 return None;
516 }
517
518 self.comment
519 .as_ref()
520 .map(|comment| ctx.options().process_comment(comment))
521 }
522
523 /// What kind of item is this?
kind(&self) -> &ItemKind524 pub(crate) fn kind(&self) -> &ItemKind {
525 &self.kind
526 }
527
528 /// Get a mutable reference to this item's kind.
kind_mut(&mut self) -> &mut ItemKind529 pub(crate) fn kind_mut(&mut self) -> &mut ItemKind {
530 &mut self.kind
531 }
532
533 /// Where in the source is this item located?
location(&self) -> Option<&clang::SourceLocation>534 pub(crate) fn location(&self) -> Option<&clang::SourceLocation> {
535 self.location.as_ref()
536 }
537
538 /// Get an identifier that differentiates this item from its siblings.
539 ///
540 /// This should stay relatively stable in the face of code motion outside or
541 /// below this item's lexical scope, meaning that this can be useful for
542 /// generating relatively stable identifiers within a scope.
local_id(&self, ctx: &BindgenContext) -> usize543 pub(crate) fn local_id(&self, ctx: &BindgenContext) -> usize {
544 *self.local_id.borrow_with(|| {
545 let parent = ctx.resolve_item(self.parent_id);
546 parent.next_child_local_id()
547 })
548 }
549
550 /// Get an identifier that differentiates a child of this item of other
551 /// related items.
552 ///
553 /// This is currently used for anonymous items, and template instantiation
554 /// tests, in both cases in order to reduce noise when system headers are at
555 /// place.
next_child_local_id(&self) -> usize556 pub(crate) fn next_child_local_id(&self) -> usize {
557 let local_id = self.next_child_local_id.get();
558 self.next_child_local_id.set(local_id + 1);
559 local_id
560 }
561
562 /// Returns whether this item is a top-level item, from the point of view of
563 /// bindgen.
564 ///
565 /// This point of view changes depending on whether namespaces are enabled
566 /// or not. That way, in the following example:
567 ///
568 /// ```c++
569 /// namespace foo {
570 /// static int var;
571 /// }
572 /// ```
573 ///
574 /// `var` would be a toplevel item if namespaces are disabled, but won't if
575 /// they aren't.
576 ///
577 /// This function is used to determine when the codegen phase should call
578 /// `codegen` on an item, since any item that is not top-level will be
579 /// generated by its parent.
is_toplevel(&self, ctx: &BindgenContext) -> bool580 pub(crate) fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
581 // FIXME: Workaround for some types falling behind when parsing weird
582 // stl classes, for example.
583 if ctx.options().enable_cxx_namespaces &&
584 self.kind().is_module() &&
585 self.id() != ctx.root_module()
586 {
587 return false;
588 }
589
590 let mut parent = self.parent_id;
591 loop {
592 let parent_item = match ctx.resolve_item_fallible(parent) {
593 Some(item) => item,
594 None => return false,
595 };
596
597 if parent_item.id() == ctx.root_module() {
598 return true;
599 } else if ctx.options().enable_cxx_namespaces ||
600 !parent_item.kind().is_module()
601 {
602 return false;
603 }
604
605 parent = parent_item.parent_id();
606 }
607 }
608
609 /// Get a reference to this item's underlying `Type`. Panic if this is some
610 /// other kind of item.
expect_type(&self) -> &Type611 pub(crate) fn expect_type(&self) -> &Type {
612 self.kind().expect_type()
613 }
614
615 /// Get a reference to this item's underlying `Type`, or `None` if this is
616 /// some other kind of item.
as_type(&self) -> Option<&Type>617 pub(crate) fn as_type(&self) -> Option<&Type> {
618 self.kind().as_type()
619 }
620
621 /// Get a reference to this item's underlying `Function`. Panic if this is
622 /// some other kind of item.
expect_function(&self) -> &Function623 pub(crate) fn expect_function(&self) -> &Function {
624 self.kind().expect_function()
625 }
626
627 /// Is this item a module?
is_module(&self) -> bool628 pub(crate) fn is_module(&self) -> bool {
629 matches!(self.kind, ItemKind::Module(..))
630 }
631
632 /// Get this item's annotations.
annotations(&self) -> &Annotations633 pub(crate) fn annotations(&self) -> &Annotations {
634 &self.annotations
635 }
636
637 /// Whether this item should be blocklisted.
638 ///
639 /// This may be due to either annotations or to other kind of configuration.
is_blocklisted(&self, ctx: &BindgenContext) -> bool640 pub(crate) fn is_blocklisted(&self, ctx: &BindgenContext) -> bool {
641 debug_assert!(
642 ctx.in_codegen_phase(),
643 "You're not supposed to call this yet"
644 );
645 if self.annotations.hide() {
646 return true;
647 }
648
649 if !ctx.options().blocklisted_files.is_empty() {
650 if let Some(location) = &self.location {
651 let (file, _, _, _) = location.location();
652 if let Some(filename) = file.name() {
653 if ctx.options().blocklisted_files.matches(filename) {
654 return true;
655 }
656 }
657 }
658 }
659
660 let path = self.path_for_allowlisting(ctx);
661 let name = path[1..].join("::");
662 ctx.options().blocklisted_items.matches(&name) ||
663 match self.kind {
664 ItemKind::Type(..) => {
665 ctx.options().blocklisted_types.matches(&name) ||
666 ctx.is_replaced_type(path, self.id)
667 }
668 ItemKind::Function(..) => {
669 ctx.options().blocklisted_functions.matches(&name)
670 }
671 // TODO: Add constant / namespace blocklisting?
672 ItemKind::Var(..) | ItemKind::Module(..) => false,
673 }
674 }
675
676 /// Take out item NameOptions
name<'a>( &'a self, ctx: &'a BindgenContext, ) -> NameOptions<'a>677 pub(crate) fn name<'a>(
678 &'a self,
679 ctx: &'a BindgenContext,
680 ) -> NameOptions<'a> {
681 NameOptions::new(self, ctx)
682 }
683
684 /// Get the target item ID for name generation.
name_target(&self, ctx: &BindgenContext) -> ItemId685 fn name_target(&self, ctx: &BindgenContext) -> ItemId {
686 let mut targets_seen = DebugOnlyItemSet::new();
687 let mut item = self;
688
689 loop {
690 extra_assert!(!targets_seen.contains(&item.id()));
691 targets_seen.insert(item.id());
692
693 if self.annotations().use_instead_of().is_some() {
694 return self.id();
695 }
696
697 match *item.kind() {
698 ItemKind::Type(ref ty) => match *ty.kind() {
699 TypeKind::ResolvedTypeRef(inner) => {
700 item = ctx.resolve_item(inner);
701 }
702 TypeKind::TemplateInstantiation(ref inst) => {
703 item = ctx.resolve_item(inst.template_definition());
704 }
705 _ => return item.id(),
706 },
707 _ => return item.id(),
708 }
709 }
710 }
711
712 /// Create a fully disambiguated name for an item, including template
713 /// parameters if it is a type
full_disambiguated_name( &self, ctx: &BindgenContext, ) -> String714 pub(crate) fn full_disambiguated_name(
715 &self,
716 ctx: &BindgenContext,
717 ) -> String {
718 let mut s = String::new();
719 let level = 0;
720 self.push_disambiguated_name(ctx, &mut s, level);
721 s
722 }
723
724 /// Helper function for full_disambiguated_name
push_disambiguated_name( &self, ctx: &BindgenContext, to: &mut String, level: u8, )725 fn push_disambiguated_name(
726 &self,
727 ctx: &BindgenContext,
728 to: &mut String,
729 level: u8,
730 ) {
731 to.push_str(&self.canonical_name(ctx));
732 if let ItemKind::Type(ref ty) = *self.kind() {
733 if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() {
734 to.push_str(&format!("_open{}_", level));
735 for arg in inst.template_arguments() {
736 arg.into_resolver()
737 .through_type_refs()
738 .resolve(ctx)
739 .push_disambiguated_name(ctx, to, level + 1);
740 to.push('_');
741 }
742 to.push_str(&format!("close{}", level));
743 }
744 }
745 }
746
747 /// Get this function item's name, or `None` if this item is not a function.
func_name(&self) -> Option<&str>748 fn func_name(&self) -> Option<&str> {
749 match *self.kind() {
750 ItemKind::Function(ref func) => Some(func.name()),
751 _ => None,
752 }
753 }
754
755 /// Get the overload index for this method. If this is not a method, return
756 /// `None`.
overload_index(&self, ctx: &BindgenContext) -> Option<usize>757 fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> {
758 self.func_name().and_then(|func_name| {
759 let parent = ctx.resolve_item(self.parent_id());
760 if let ItemKind::Type(ref ty) = *parent.kind() {
761 if let TypeKind::Comp(ref ci) = *ty.kind() {
762 // All the constructors have the same name, so no need to
763 // resolve and check.
764 return ci
765 .constructors()
766 .iter()
767 .position(|c| *c == self.id())
768 .or_else(|| {
769 ci.methods()
770 .iter()
771 .filter(|m| {
772 let item = ctx.resolve_item(m.signature());
773 let func = item.expect_function();
774 func.name() == func_name
775 })
776 .position(|m| m.signature() == self.id())
777 });
778 }
779 }
780
781 None
782 })
783 }
784
785 /// Get this item's base name (aka non-namespaced name).
base_name(&self, ctx: &BindgenContext) -> String786 fn base_name(&self, ctx: &BindgenContext) -> String {
787 if let Some(path) = self.annotations().use_instead_of() {
788 return path.last().unwrap().clone();
789 }
790
791 match *self.kind() {
792 ItemKind::Var(ref var) => var.name().to_owned(),
793 ItemKind::Module(ref module) => {
794 module.name().map(ToOwned::to_owned).unwrap_or_else(|| {
795 format!("_bindgen_mod_{}", self.exposed_id(ctx))
796 })
797 }
798 ItemKind::Type(ref ty) => {
799 ty.sanitized_name(ctx).map(Into::into).unwrap_or_else(|| {
800 format!("_bindgen_ty_{}", self.exposed_id(ctx))
801 })
802 }
803 ItemKind::Function(ref fun) => {
804 let mut name = fun.name().to_owned();
805
806 if let Some(idx) = self.overload_index(ctx) {
807 if idx > 0 {
808 write!(&mut name, "{}", idx).unwrap();
809 }
810 }
811
812 name
813 }
814 }
815 }
816
is_anon(&self) -> bool817 fn is_anon(&self) -> bool {
818 match self.kind() {
819 ItemKind::Module(module) => module.name().is_none(),
820 ItemKind::Type(ty) => ty.name().is_none(),
821 ItemKind::Function(_) => false,
822 ItemKind::Var(_) => false,
823 }
824 }
825
826 /// Get the canonical name without taking into account the replaces
827 /// annotation.
828 ///
829 /// This is the base logic used to implement hiding and replacing via
830 /// annotations, and also to implement proper name mangling.
831 ///
832 /// The idea is that each generated type in the same "level" (read: module
833 /// or namespace) has a unique canonical name.
834 ///
835 /// This name should be derived from the immutable state contained in the
836 /// type and the parent chain, since it should be consistent.
837 ///
838 /// If `BindgenOptions::disable_nested_struct_naming` is true then returned
839 /// name is the inner most non-anonymous name plus all the anonymous base names
840 /// that follows.
real_canonical_name( &self, ctx: &BindgenContext, opt: &NameOptions, ) -> String841 pub(crate) fn real_canonical_name(
842 &self,
843 ctx: &BindgenContext,
844 opt: &NameOptions,
845 ) -> String {
846 let target = ctx.resolve_item(self.name_target(ctx));
847
848 // Short-circuit if the target has an override, and just use that.
849 if let Some(path) = target.annotations.use_instead_of() {
850 if ctx.options().enable_cxx_namespaces {
851 return path.last().unwrap().clone();
852 }
853 return path.join("_");
854 }
855
856 let base_name = target.base_name(ctx);
857
858 // Named template type arguments are never namespaced, and never
859 // mangled.
860 if target.is_template_param(ctx, &()) {
861 return base_name;
862 }
863
864 // Ancestors' ID iter
865 let mut ids_iter = target
866 .parent_id()
867 .ancestors(ctx)
868 .filter(|id| *id != ctx.root_module())
869 .take_while(|id| {
870 // Stop iterating ancestors once we reach a non-inline namespace
871 // when opt.within_namespaces is set.
872 !opt.within_namespaces || !ctx.resolve_item(*id).is_module()
873 })
874 .filter(|id| {
875 if !ctx.options().conservative_inline_namespaces {
876 if let ItemKind::Module(ref module) =
877 *ctx.resolve_item(*id).kind()
878 {
879 return !module.is_inline();
880 }
881 }
882
883 true
884 });
885
886 let ids: Vec<_> = if ctx.options().disable_nested_struct_naming {
887 let mut ids = Vec::new();
888
889 // If target is anonymous we need find its first named ancestor.
890 if target.is_anon() {
891 for id in ids_iter.by_ref() {
892 ids.push(id);
893
894 if !ctx.resolve_item(id).is_anon() {
895 break;
896 }
897 }
898 }
899
900 ids
901 } else {
902 ids_iter.collect()
903 };
904
905 // Concatenate this item's ancestors' names together.
906 let mut names: Vec<_> = ids
907 .into_iter()
908 .map(|id| {
909 let item = ctx.resolve_item(id);
910 let target = ctx.resolve_item(item.name_target(ctx));
911 target.base_name(ctx)
912 })
913 .filter(|name| !name.is_empty())
914 .collect();
915
916 names.reverse();
917
918 if !base_name.is_empty() {
919 names.push(base_name);
920 }
921
922 if ctx.options().c_naming {
923 if let Some(prefix) = self.c_naming_prefix() {
924 names.insert(0, prefix.to_string());
925 }
926 }
927
928 let name = names.join("_");
929
930 let name = if opt.user_mangled == UserMangled::Yes {
931 ctx.options()
932 .last_callback(|callbacks| callbacks.item_name(&name))
933 .unwrap_or(name)
934 } else {
935 name
936 };
937
938 ctx.rust_mangle(&name).into_owned()
939 }
940
941 /// The exposed ID that represents an unique ID among the siblings of a
942 /// given item.
exposed_id(&self, ctx: &BindgenContext) -> String943 pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String {
944 // Only use local ids for enums, classes, structs and union types. All
945 // other items use their global ID.
946 let ty_kind = self.kind().as_type().map(|t| t.kind());
947 if let Some(ty_kind) = ty_kind {
948 match *ty_kind {
949 TypeKind::Comp(..) |
950 TypeKind::TemplateInstantiation(..) |
951 TypeKind::Enum(..) => return self.local_id(ctx).to_string(),
952 _ => {}
953 }
954 }
955
956 // Note that this `id_` prefix prevents (really unlikely) collisions
957 // between the global ID and the local ID of an item with the same
958 // parent.
959 format!("id_{}", self.id().as_usize())
960 }
961
962 /// Get a reference to this item's `Module`, or `None` if this is not a
963 /// `Module` item.
as_module(&self) -> Option<&Module>964 pub(crate) fn as_module(&self) -> Option<&Module> {
965 match self.kind {
966 ItemKind::Module(ref module) => Some(module),
967 _ => None,
968 }
969 }
970
971 /// Get a mutable reference to this item's `Module`, or `None` if this is
972 /// not a `Module` item.
as_module_mut(&mut self) -> Option<&mut Module>973 pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> {
974 match self.kind {
975 ItemKind::Module(ref mut module) => Some(module),
976 _ => None,
977 }
978 }
979
980 /// Returns whether the item is a constified module enum
is_constified_enum_module(&self, ctx: &BindgenContext) -> bool981 fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
982 // Do not jump through aliases, except for aliases that point to a type
983 // with the same name, since we dont generate coe for them.
984 let item = self.id.into_resolver().through_type_refs().resolve(ctx);
985 let type_ = match *item.kind() {
986 ItemKind::Type(ref type_) => type_,
987 _ => return false,
988 };
989
990 match *type_.kind() {
991 TypeKind::Enum(ref enum_) => {
992 enum_.computed_enum_variation(ctx, self) ==
993 EnumVariation::ModuleConsts
994 }
995 TypeKind::Alias(inner_id) => {
996 // TODO(emilio): Make this "hop through type aliases that aren't
997 // really generated" an option in `ItemResolver`?
998 let inner_item = ctx.resolve_item(inner_id);
999 let name = item.canonical_name(ctx);
1000
1001 if inner_item.canonical_name(ctx) == name {
1002 inner_item.is_constified_enum_module(ctx)
1003 } else {
1004 false
1005 }
1006 }
1007 _ => false,
1008 }
1009 }
1010
1011 /// Is this item of a kind that is enabled for code generation?
is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool1012 pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
1013 let cc = &ctx.options().codegen_config;
1014 match *self.kind() {
1015 ItemKind::Module(..) => true,
1016 ItemKind::Var(_) => cc.vars(),
1017 ItemKind::Type(_) => cc.types(),
1018 ItemKind::Function(ref f) => match f.kind() {
1019 FunctionKind::Function => cc.functions(),
1020 FunctionKind::Method(MethodKind::Constructor) => {
1021 cc.constructors()
1022 }
1023 FunctionKind::Method(MethodKind::Destructor) |
1024 FunctionKind::Method(MethodKind::VirtualDestructor {
1025 ..
1026 }) => cc.destructors(),
1027 FunctionKind::Method(MethodKind::Static) |
1028 FunctionKind::Method(MethodKind::Normal) |
1029 FunctionKind::Method(MethodKind::Virtual { .. }) => {
1030 cc.methods()
1031 }
1032 },
1033 }
1034 }
1035
1036 /// Returns the path we should use for allowlisting / blocklisting, which
1037 /// doesn't include user-mangling.
path_for_allowlisting( &self, ctx: &BindgenContext, ) -> &Vec<String>1038 pub(crate) fn path_for_allowlisting(
1039 &self,
1040 ctx: &BindgenContext,
1041 ) -> &Vec<String> {
1042 self.path_for_allowlisting
1043 .borrow_with(|| self.compute_path(ctx, UserMangled::No))
1044 }
1045
compute_path( &self, ctx: &BindgenContext, mangled: UserMangled, ) -> Vec<String>1046 fn compute_path(
1047 &self,
1048 ctx: &BindgenContext,
1049 mangled: UserMangled,
1050 ) -> Vec<String> {
1051 if let Some(path) = self.annotations().use_instead_of() {
1052 let mut ret =
1053 vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
1054 ret.extend_from_slice(path);
1055 return ret;
1056 }
1057
1058 let target = ctx.resolve_item(self.name_target(ctx));
1059 let mut path: Vec<_> = target
1060 .ancestors(ctx)
1061 .chain(iter::once(ctx.root_module().into()))
1062 .map(|id| ctx.resolve_item(id))
1063 .filter(|item| {
1064 item.id() == target.id() ||
1065 item.as_module().map_or(false, |module| {
1066 !module.is_inline() ||
1067 ctx.options().conservative_inline_namespaces
1068 })
1069 })
1070 .map(|item| {
1071 ctx.resolve_item(item.name_target(ctx))
1072 .name(ctx)
1073 .within_namespaces()
1074 .user_mangled(mangled)
1075 .get()
1076 })
1077 .collect();
1078 path.reverse();
1079 path
1080 }
1081
1082 /// Returns a prefix for the canonical name when C naming is enabled.
c_naming_prefix(&self) -> Option<&str>1083 fn c_naming_prefix(&self) -> Option<&str> {
1084 let ty = match self.kind {
1085 ItemKind::Type(ref ty) => ty,
1086 _ => return None,
1087 };
1088
1089 Some(match ty.kind() {
1090 TypeKind::Comp(ref ci) => match ci.kind() {
1091 CompKind::Struct => "struct",
1092 CompKind::Union => "union",
1093 },
1094 TypeKind::Enum(..) => "enum",
1095 _ => return None,
1096 })
1097 }
1098
1099 /// Whether this is a `#[must_use]` type.
must_use(&self, ctx: &BindgenContext) -> bool1100 pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
1101 self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
1102 }
1103 }
1104
1105 impl<T> IsOpaque for T
1106 where
1107 T: Copy + Into<ItemId>,
1108 {
1109 type Extra = ();
1110
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1111 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1112 debug_assert!(
1113 ctx.in_codegen_phase(),
1114 "You're not supposed to call this yet"
1115 );
1116 ctx.resolve_item((*self).into()).is_opaque(ctx, &())
1117 }
1118 }
1119
1120 impl IsOpaque for Item {
1121 type Extra = ();
1122
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1123 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1124 debug_assert!(
1125 ctx.in_codegen_phase(),
1126 "You're not supposed to call this yet"
1127 );
1128 self.annotations.opaque() ||
1129 self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) ||
1130 ctx.opaque_by_name(self.path_for_allowlisting(ctx))
1131 }
1132 }
1133
1134 impl<T> HasVtable for T
1135 where
1136 T: Copy + Into<ItemId>,
1137 {
has_vtable(&self, ctx: &BindgenContext) -> bool1138 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1139 let id: ItemId = (*self).into();
1140 id.as_type_id(ctx).map_or(false, |id| {
1141 !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No)
1142 })
1143 }
1144
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1145 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1146 let id: ItemId = (*self).into();
1147 id.as_type_id(ctx).map_or(false, |id| {
1148 matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable)
1149 })
1150 }
1151 }
1152
1153 impl HasVtable for Item {
has_vtable(&self, ctx: &BindgenContext) -> bool1154 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1155 self.id().has_vtable(ctx)
1156 }
1157
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1158 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1159 self.id().has_vtable_ptr(ctx)
1160 }
1161 }
1162
1163 impl<T> Sizedness for T
1164 where
1165 T: Copy + Into<ItemId>,
1166 {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1167 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1168 let id: ItemId = (*self).into();
1169 id.as_type_id(ctx)
1170 .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id))
1171 }
1172 }
1173
1174 impl Sizedness for Item {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1175 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1176 self.id().sizedness(ctx)
1177 }
1178 }
1179
1180 impl<T> HasTypeParamInArray for T
1181 where
1182 T: Copy + Into<ItemId>,
1183 {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1184 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1185 debug_assert!(
1186 ctx.in_codegen_phase(),
1187 "You're not supposed to call this yet"
1188 );
1189 ctx.lookup_has_type_param_in_array(*self)
1190 }
1191 }
1192
1193 impl HasTypeParamInArray for Item {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1194 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1195 debug_assert!(
1196 ctx.in_codegen_phase(),
1197 "You're not supposed to call this yet"
1198 );
1199 ctx.lookup_has_type_param_in_array(self.id())
1200 }
1201 }
1202
1203 impl<T> HasFloat for T
1204 where
1205 T: Copy + Into<ItemId>,
1206 {
has_float(&self, ctx: &BindgenContext) -> bool1207 fn has_float(&self, ctx: &BindgenContext) -> bool {
1208 debug_assert!(
1209 ctx.in_codegen_phase(),
1210 "You're not supposed to call this yet"
1211 );
1212 ctx.lookup_has_float(*self)
1213 }
1214 }
1215
1216 impl HasFloat for Item {
has_float(&self, ctx: &BindgenContext) -> bool1217 fn has_float(&self, ctx: &BindgenContext) -> bool {
1218 debug_assert!(
1219 ctx.in_codegen_phase(),
1220 "You're not supposed to call this yet"
1221 );
1222 ctx.lookup_has_float(self.id())
1223 }
1224 }
1225
1226 /// A set of items.
1227 pub(crate) type ItemSet = BTreeSet<ItemId>;
1228
1229 impl DotAttributes for Item {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,1230 fn dot_attributes<W>(
1231 &self,
1232 ctx: &BindgenContext,
1233 out: &mut W,
1234 ) -> io::Result<()>
1235 where
1236 W: io::Write,
1237 {
1238 writeln!(
1239 out,
1240 "<tr><td>{:?}</td></tr>
1241 <tr><td>name</td><td>{}</td></tr>",
1242 self.id,
1243 self.name(ctx).get()
1244 )?;
1245
1246 if self.is_opaque(ctx, &()) {
1247 writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
1248 }
1249
1250 self.kind.dot_attributes(ctx, out)
1251 }
1252 }
1253
1254 impl<T> TemplateParameters for T
1255 where
1256 T: Copy + Into<ItemId>,
1257 {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1258 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1259 ctx.resolve_item_fallible(*self)
1260 .map_or(vec![], |item| item.self_template_params(ctx))
1261 }
1262 }
1263
1264 impl TemplateParameters for Item {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1265 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1266 self.kind.self_template_params(ctx)
1267 }
1268 }
1269
1270 impl TemplateParameters for ItemKind {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1271 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1272 match *self {
1273 ItemKind::Type(ref ty) => ty.self_template_params(ctx),
1274 // If we start emitting bindings to explicitly instantiated
1275 // functions, then we'll need to check ItemKind::Function for
1276 // template params.
1277 ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => {
1278 vec![]
1279 }
1280 }
1281 }
1282 }
1283
1284 // An utility function to handle recursing inside nested types.
visit_child( cur: clang::Cursor, id: ItemId, ty: &clang::Type, parent_id: Option<ItemId>, ctx: &mut BindgenContext, result: &mut Result<TypeId, ParseError>, ) -> clang_sys::CXChildVisitResult1285 fn visit_child(
1286 cur: clang::Cursor,
1287 id: ItemId,
1288 ty: &clang::Type,
1289 parent_id: Option<ItemId>,
1290 ctx: &mut BindgenContext,
1291 result: &mut Result<TypeId, ParseError>,
1292 ) -> clang_sys::CXChildVisitResult {
1293 use clang_sys::*;
1294 if result.is_ok() {
1295 return CXChildVisit_Break;
1296 }
1297
1298 *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
1299
1300 match *result {
1301 Ok(..) => CXChildVisit_Break,
1302 Err(ParseError::Recurse) => {
1303 cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result));
1304 CXChildVisit_Continue
1305 }
1306 Err(ParseError::Continue) => CXChildVisit_Continue,
1307 }
1308 }
1309
1310 impl Item {
1311 /// Create a builtin type.
builtin_type( kind: TypeKind, is_const: bool, ctx: &mut BindgenContext, ) -> TypeId1312 pub(crate) fn builtin_type(
1313 kind: TypeKind,
1314 is_const: bool,
1315 ctx: &mut BindgenContext,
1316 ) -> TypeId {
1317 // Feel free to add more here, I'm just lazy.
1318 match kind {
1319 TypeKind::Void |
1320 TypeKind::Int(..) |
1321 TypeKind::Pointer(..) |
1322 TypeKind::Float(..) => {}
1323 _ => panic!("Unsupported builtin type"),
1324 }
1325
1326 let ty = Type::new(None, None, kind, is_const);
1327 let id = ctx.next_item_id();
1328 let module = ctx.root_module().into();
1329 ctx.add_item(
1330 Item::new(id, None, None, module, ItemKind::Type(ty), None),
1331 None,
1332 None,
1333 );
1334 id.as_type_id_unchecked()
1335 }
1336
1337 /// Parse this item from the given Clang cursor.
parse( cursor: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<ItemId, ParseError>1338 pub(crate) fn parse(
1339 cursor: clang::Cursor,
1340 parent_id: Option<ItemId>,
1341 ctx: &mut BindgenContext,
1342 ) -> Result<ItemId, ParseError> {
1343 use crate::ir::var::Var;
1344 use clang_sys::*;
1345
1346 if !cursor.is_valid() {
1347 return Err(ParseError::Continue);
1348 }
1349
1350 let comment = cursor.raw_comment();
1351 let annotations = Annotations::new(&cursor);
1352
1353 let current_module = ctx.current_module().into();
1354 let relevant_parent_id = parent_id.unwrap_or(current_module);
1355
1356 #[allow(clippy::missing_docs_in_private_items)]
1357 macro_rules! try_parse {
1358 ($what:ident) => {
1359 match $what::parse(cursor, ctx) {
1360 Ok(ParseResult::New(item, declaration)) => {
1361 let id = ctx.next_item_id();
1362
1363 ctx.add_item(
1364 Item::new(
1365 id,
1366 comment,
1367 annotations,
1368 relevant_parent_id,
1369 ItemKind::$what(item),
1370 Some(cursor.location()),
1371 ),
1372 declaration,
1373 Some(cursor),
1374 );
1375 return Ok(id);
1376 }
1377 Ok(ParseResult::AlreadyResolved(id)) => {
1378 return Ok(id);
1379 }
1380 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1381 Err(ParseError::Continue) => {}
1382 }
1383 };
1384 }
1385
1386 try_parse!(Module);
1387
1388 // NOTE: Is extremely important to parse functions and vars **before**
1389 // types. Otherwise we can parse a function declaration as a type
1390 // (which is legal), and lose functions to generate.
1391 //
1392 // In general, I'm not totally confident this split between
1393 // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but
1394 // I guess we can try.
1395 try_parse!(Function);
1396 try_parse!(Var);
1397
1398 // Types are sort of special, so to avoid parsing template classes
1399 // twice, handle them separately.
1400 {
1401 let definition = cursor.definition();
1402 let applicable_cursor = definition.unwrap_or(cursor);
1403
1404 let relevant_parent_id = match definition {
1405 Some(definition) => {
1406 if definition != cursor {
1407 ctx.add_semantic_parent(definition, relevant_parent_id);
1408 return Ok(Item::from_ty_or_ref(
1409 applicable_cursor.cur_type(),
1410 cursor,
1411 parent_id,
1412 ctx,
1413 )
1414 .into());
1415 }
1416 ctx.known_semantic_parent(definition)
1417 .or(parent_id)
1418 .unwrap_or_else(|| ctx.current_module().into())
1419 }
1420 None => relevant_parent_id,
1421 };
1422
1423 match Item::from_ty(
1424 &applicable_cursor.cur_type(),
1425 applicable_cursor,
1426 Some(relevant_parent_id),
1427 ctx,
1428 ) {
1429 Ok(ty) => return Ok(ty.into()),
1430 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1431 Err(ParseError::Continue) => {}
1432 }
1433 }
1434
1435 // Guess how does clang treat extern "C" blocks?
1436 if cursor.kind() == CXCursor_UnexposedDecl {
1437 Err(ParseError::Recurse)
1438 } else {
1439 // We allowlist cursors here known to be unhandled, to prevent being
1440 // too noisy about this.
1441 match cursor.kind() {
1442 CXCursor_MacroDefinition |
1443 CXCursor_MacroExpansion |
1444 CXCursor_UsingDeclaration |
1445 CXCursor_UsingDirective |
1446 CXCursor_StaticAssert |
1447 CXCursor_FunctionTemplate => {
1448 debug!(
1449 "Unhandled cursor kind {:?}: {:?}",
1450 cursor.kind(),
1451 cursor
1452 );
1453 }
1454 CXCursor_InclusionDirective => {
1455 let file = cursor.get_included_file_name();
1456 match file {
1457 None => {
1458 warn!(
1459 "Inclusion of a nameless file in {:?}",
1460 cursor
1461 );
1462 }
1463 Some(included_file) => {
1464 for cb in &ctx.options().parse_callbacks {
1465 cb.include_file(&included_file);
1466 }
1467
1468 ctx.add_dep(included_file.into_boxed_str());
1469 }
1470 }
1471 }
1472 _ => {
1473 // ignore toplevel operator overloads
1474 let spelling = cursor.spelling();
1475 if !spelling.starts_with("operator") {
1476 warn!(
1477 "Unhandled cursor kind {:?}: {:?}",
1478 cursor.kind(),
1479 cursor
1480 );
1481 }
1482 }
1483 }
1484
1485 Err(ParseError::Continue)
1486 }
1487 }
1488
1489 /// Parse this item from the given Clang type, or if we haven't resolved all
1490 /// the other items this one depends on, an unresolved reference.
from_ty_or_ref( ty: clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> TypeId1491 pub(crate) fn from_ty_or_ref(
1492 ty: clang::Type,
1493 location: clang::Cursor,
1494 parent_id: Option<ItemId>,
1495 ctx: &mut BindgenContext,
1496 ) -> TypeId {
1497 let id = ctx.next_item_id();
1498 Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
1499 }
1500
1501 /// Parse a C++ type. If we find a reference to a type that has not been
1502 /// defined yet, use `UnresolvedTypeRef` as a placeholder.
1503 ///
1504 /// This logic is needed to avoid parsing items with the incorrect parent
1505 /// and it's sort of complex to explain, so I'll just point to
1506 /// `tests/headers/typeref.hpp` to see the kind of constructs that forced
1507 /// this.
1508 ///
1509 /// Typerefs are resolved once parsing is completely done, see
1510 /// `BindgenContext::resolve_typerefs`.
from_ty_or_ref_with_id( potential_id: ItemId, ty: clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> TypeId1511 pub(crate) fn from_ty_or_ref_with_id(
1512 potential_id: ItemId,
1513 ty: clang::Type,
1514 location: clang::Cursor,
1515 parent_id: Option<ItemId>,
1516 ctx: &mut BindgenContext,
1517 ) -> TypeId {
1518 debug!(
1519 "from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}",
1520 potential_id, ty, location, parent_id
1521 );
1522
1523 if ctx.collected_typerefs() {
1524 debug!("refs already collected, resolving directly");
1525 return Item::from_ty_with_id(
1526 potential_id,
1527 &ty,
1528 location,
1529 parent_id,
1530 ctx,
1531 )
1532 .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx));
1533 }
1534
1535 if let Some(ty) = ctx.builtin_or_resolved_ty(
1536 potential_id,
1537 parent_id,
1538 &ty,
1539 Some(location),
1540 ) {
1541 debug!("{:?} already resolved: {:?}", ty, location);
1542 return ty;
1543 }
1544
1545 debug!("New unresolved type reference: {:?}, {:?}", ty, location);
1546
1547 let is_const = ty.is_const();
1548 let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
1549 let current_module = ctx.current_module();
1550
1551 ctx.add_item(
1552 Item::new(
1553 potential_id,
1554 None,
1555 None,
1556 parent_id.unwrap_or_else(|| current_module.into()),
1557 ItemKind::Type(Type::new(None, None, kind, is_const)),
1558 Some(location.location()),
1559 ),
1560 None,
1561 None,
1562 );
1563 potential_id.as_type_id_unchecked()
1564 }
1565
1566 /// Parse this item from the given Clang type. See [`Item::from_ty_with_id`].
from_ty( ty: &clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<TypeId, ParseError>1567 pub(crate) fn from_ty(
1568 ty: &clang::Type,
1569 location: clang::Cursor,
1570 parent_id: Option<ItemId>,
1571 ctx: &mut BindgenContext,
1572 ) -> Result<TypeId, ParseError> {
1573 let id = ctx.next_item_id();
1574 Item::from_ty_with_id(id, ty, location, parent_id, ctx)
1575 }
1576
1577 /// This is one of the trickiest methods you'll find (probably along with
1578 /// some of the ones that handle templates in `BindgenContext`).
1579 ///
1580 /// This method parses a type, given the potential ID of that type (if
1581 /// parsing it was correct), an optional location we're scanning, which is
1582 /// critical some times to obtain information, an optional parent item ID,
1583 /// that will, if it's `None`, become the current module ID, and the
1584 /// context.
from_ty_with_id( id: ItemId, ty: &clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<TypeId, ParseError>1585 pub(crate) fn from_ty_with_id(
1586 id: ItemId,
1587 ty: &clang::Type,
1588 location: clang::Cursor,
1589 parent_id: Option<ItemId>,
1590 ctx: &mut BindgenContext,
1591 ) -> Result<TypeId, ParseError> {
1592 use clang_sys::*;
1593
1594 debug!(
1595 "Item::from_ty_with_id: {:?}\n\
1596 \tty = {:?},\n\
1597 \tlocation = {:?}",
1598 id, ty, location
1599 );
1600
1601 if ty.kind() == clang_sys::CXType_Unexposed ||
1602 location.cur_type().kind() == clang_sys::CXType_Unexposed
1603 {
1604 if ty.is_associated_type() ||
1605 location.cur_type().is_associated_type()
1606 {
1607 return Ok(Item::new_opaque_type(id, ty, ctx));
1608 }
1609
1610 if let Some(param_id) = Item::type_param(None, location, ctx) {
1611 return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
1612 }
1613 }
1614
1615 // Treat all types that are declared inside functions as opaque. The Rust binding
1616 // won't be able to do anything with them anyway.
1617 //
1618 // (If we don't do this check here, we can have subtle logic bugs because we generally
1619 // ignore function bodies. See issue #2036.)
1620 if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
1621 if FunctionKind::from_cursor(parent).is_some() {
1622 debug!("Skipping type declared inside function: {:?}", ty);
1623 return Ok(Item::new_opaque_type(id, ty, ctx));
1624 }
1625 }
1626
1627 let decl = {
1628 let canonical_def = ty.canonical_type().declaration().definition();
1629 canonical_def.unwrap_or_else(|| ty.declaration())
1630 };
1631
1632 let comment = location
1633 .raw_comment()
1634 .or_else(|| decl.raw_comment())
1635 .or_else(|| location.raw_comment());
1636
1637 let annotations =
1638 Annotations::new(&decl).or_else(|| Annotations::new(&location));
1639
1640 if let Some(ref annotations) = annotations {
1641 if let Some(replaced) = annotations.use_instead_of() {
1642 ctx.replace(replaced, id);
1643 }
1644 }
1645
1646 if let Some(ty) =
1647 ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location))
1648 {
1649 return Ok(ty);
1650 }
1651
1652 // First, check we're not recursing.
1653 let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
1654 let declaration_to_look_for = if valid_decl {
1655 decl.canonical()
1656 } else if location.kind() == CXCursor_ClassTemplate {
1657 valid_decl = true;
1658 location
1659 } else {
1660 decl
1661 };
1662
1663 if valid_decl {
1664 if let Some(partial) = ctx
1665 .currently_parsed_types()
1666 .iter()
1667 .find(|ty| *ty.decl() == declaration_to_look_for)
1668 {
1669 debug!("Avoiding recursion parsing type: {:?}", ty);
1670 // Unchecked because we haven't finished this type yet.
1671 return Ok(partial.id().as_type_id_unchecked());
1672 }
1673 }
1674
1675 let current_module = ctx.current_module().into();
1676 let partial_ty = PartialType::new(declaration_to_look_for, id);
1677 if valid_decl {
1678 ctx.begin_parsing(partial_ty);
1679 }
1680
1681 let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
1682 let relevant_parent_id = parent_id.unwrap_or(current_module);
1683 let ret = match result {
1684 Ok(ParseResult::AlreadyResolved(ty)) => {
1685 Ok(ty.as_type_id_unchecked())
1686 }
1687 Ok(ParseResult::New(item, declaration)) => {
1688 ctx.add_item(
1689 Item::new(
1690 id,
1691 comment,
1692 annotations,
1693 relevant_parent_id,
1694 ItemKind::Type(item),
1695 Some(location.location()),
1696 ),
1697 declaration,
1698 Some(location),
1699 );
1700 Ok(id.as_type_id_unchecked())
1701 }
1702 Err(ParseError::Continue) => Err(ParseError::Continue),
1703 Err(ParseError::Recurse) => {
1704 debug!("Item::from_ty recursing in the ast");
1705 let mut result = Err(ParseError::Recurse);
1706
1707 // Need to pop here, otherwise we'll get stuck.
1708 //
1709 // TODO: Find a nicer interface, really. Also, the
1710 // declaration_to_look_for suspiciously shares a lot of
1711 // logic with ir::context, so we should refactor that.
1712 if valid_decl {
1713 let finished = ctx.finish_parsing();
1714 assert_eq!(*finished.decl(), declaration_to_look_for);
1715 }
1716
1717 location.visit(|cur| {
1718 visit_child(cur, id, ty, parent_id, ctx, &mut result)
1719 });
1720
1721 if valid_decl {
1722 let partial_ty =
1723 PartialType::new(declaration_to_look_for, id);
1724 ctx.begin_parsing(partial_ty);
1725 }
1726
1727 // If we have recursed into the AST all we know, and we still
1728 // haven't found what we've got, let's just try and make a named
1729 // type.
1730 //
1731 // This is what happens with some template members, for example.
1732 if let Err(ParseError::Recurse) = result {
1733 warn!(
1734 "Unknown type, assuming named template type: \
1735 id = {:?}; spelling = {}",
1736 id,
1737 ty.spelling()
1738 );
1739 Item::type_param(Some(id), location, ctx)
1740 .map(Ok)
1741 .unwrap_or(Err(ParseError::Recurse))
1742 } else {
1743 result
1744 }
1745 }
1746 };
1747
1748 if valid_decl {
1749 let partial_ty = ctx.finish_parsing();
1750 assert_eq!(*partial_ty.decl(), declaration_to_look_for);
1751 }
1752
1753 ret
1754 }
1755
1756 /// A named type is a template parameter, e.g., the `T` in `Foo<T>`. They're always local so
1757 /// it's the only exception when there's no declaration for a type.
type_param( with_id: Option<ItemId>, location: clang::Cursor, ctx: &mut BindgenContext, ) -> Option<TypeId>1758 pub(crate) fn type_param(
1759 with_id: Option<ItemId>,
1760 location: clang::Cursor,
1761 ctx: &mut BindgenContext,
1762 ) -> Option<TypeId> {
1763 let ty = location.cur_type();
1764
1765 debug!(
1766 "Item::type_param:\n\
1767 \twith_id = {:?},\n\
1768 \tty = {} {:?},\n\
1769 \tlocation: {:?}",
1770 with_id,
1771 ty.spelling(),
1772 ty,
1773 location
1774 );
1775
1776 if ty.kind() != clang_sys::CXType_Unexposed {
1777 // If the given cursor's type's kind is not Unexposed, then we
1778 // aren't looking at a template parameter. This check may need to be
1779 // updated in the future if they start properly exposing template
1780 // type parameters.
1781 return None;
1782 }
1783
1784 let ty_spelling = ty.spelling();
1785
1786 // Clang does not expose any information about template type parameters
1787 // via their clang::Type, nor does it give us their canonical cursors
1788 // the straightforward way. However, there are three situations from
1789 // which we can find the definition of the template type parameter, if
1790 // the cursor is indeed looking at some kind of a template type
1791 // parameter or use of one:
1792 //
1793 // 1. The cursor is pointing at the template type parameter's
1794 // definition. This is the trivial case.
1795 //
1796 // (kind = TemplateTypeParameter, ...)
1797 //
1798 // 2. The cursor is pointing at a TypeRef whose referenced() cursor is
1799 // situation (1).
1800 //
1801 // (kind = TypeRef,
1802 // referenced = (kind = TemplateTypeParameter, ...),
1803 // ...)
1804 //
1805 // 3. The cursor is pointing at some use of a template type parameter
1806 // (for example, in a FieldDecl), and this cursor has a child cursor
1807 // whose spelling is the same as the parent's type's spelling, and whose
1808 // kind is a TypeRef of the situation (2) variety.
1809 //
1810 // (kind = FieldDecl,
1811 // type = (kind = Unexposed,
1812 // spelling = "T",
1813 // ...),
1814 // children =
1815 // (kind = TypeRef,
1816 // spelling = "T",
1817 // referenced = (kind = TemplateTypeParameter,
1818 // spelling = "T",
1819 // ...),
1820 // ...)
1821 // ...)
1822 //
1823 // TODO: The alternative to this hacky pattern matching would be to
1824 // maintain proper scopes of template parameters while parsing and use
1825 // de Brujin indices to access template parameters, which clang exposes
1826 // in the cursor's type's canonical type's spelling:
1827 // "type-parameter-x-y". That is probably a better approach long-term,
1828 // but maintaining these scopes properly would require more changes to
1829 // the whole libclang -> IR parsing code.
1830
1831 fn is_template_with_spelling(
1832 refd: &clang::Cursor,
1833 spelling: &str,
1834 ) -> bool {
1835 lazy_static! {
1836 static ref ANON_TYPE_PARAM_RE: regex::Regex =
1837 regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap();
1838 }
1839
1840 if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter {
1841 return false;
1842 }
1843
1844 let refd_spelling = refd.spelling();
1845 refd_spelling == spelling ||
1846 // Allow for anonymous template parameters.
1847 (refd_spelling.is_empty() && ANON_TYPE_PARAM_RE.is_match(spelling.as_ref()))
1848 }
1849
1850 let definition = if is_template_with_spelling(&location, &ty_spelling) {
1851 // Situation (1)
1852 location
1853 } else if location.kind() == clang_sys::CXCursor_TypeRef {
1854 // Situation (2)
1855 match location.referenced() {
1856 Some(refd)
1857 if is_template_with_spelling(&refd, &ty_spelling) =>
1858 {
1859 refd
1860 }
1861 _ => return None,
1862 }
1863 } else {
1864 // Situation (3)
1865 let mut definition = None;
1866
1867 location.visit(|child| {
1868 let child_ty = child.cur_type();
1869 if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
1870 child_ty.spelling() == ty_spelling
1871 {
1872 match child.referenced() {
1873 Some(refd)
1874 if is_template_with_spelling(
1875 &refd,
1876 &ty_spelling,
1877 ) =>
1878 {
1879 definition = Some(refd);
1880 return clang_sys::CXChildVisit_Break;
1881 }
1882 _ => {}
1883 }
1884 }
1885
1886 clang_sys::CXChildVisit_Continue
1887 });
1888
1889 definition?
1890 };
1891 assert!(is_template_with_spelling(&definition, &ty_spelling));
1892
1893 // Named types are always parented to the root module. They are never
1894 // referenced with namespace prefixes, and they can't inherit anything
1895 // from their parent either, so it is simplest to just hang them off
1896 // something we know will always exist.
1897 let parent = ctx.root_module().into();
1898
1899 if let Some(id) = ctx.get_type_param(&definition) {
1900 if let Some(with_id) = with_id {
1901 return Some(ctx.build_ty_wrapper(
1902 with_id,
1903 id,
1904 Some(parent),
1905 &ty,
1906 ));
1907 } else {
1908 return Some(id);
1909 }
1910 }
1911
1912 // See tests/headers/const_tparam.hpp and
1913 // tests/headers/variadic_tname.hpp.
1914 let name = ty_spelling.replace("const ", "").replace('.', "");
1915
1916 let id = with_id.unwrap_or_else(|| ctx.next_item_id());
1917 let item = Item::new(
1918 id,
1919 None,
1920 None,
1921 parent,
1922 ItemKind::Type(Type::named(name)),
1923 Some(location.location()),
1924 );
1925 ctx.add_type_param(item, definition);
1926 Some(id.as_type_id_unchecked())
1927 }
1928 }
1929
1930 impl ItemCanonicalName for Item {
canonical_name(&self, ctx: &BindgenContext) -> String1931 fn canonical_name(&self, ctx: &BindgenContext) -> String {
1932 debug_assert!(
1933 ctx.in_codegen_phase(),
1934 "You're not supposed to call this yet"
1935 );
1936 self.canonical_name
1937 .borrow_with(|| {
1938 let in_namespace = ctx.options().enable_cxx_namespaces ||
1939 ctx.options().disable_name_namespacing;
1940
1941 if in_namespace {
1942 self.name(ctx).within_namespaces().get()
1943 } else {
1944 self.name(ctx).get()
1945 }
1946 })
1947 .clone()
1948 }
1949 }
1950
1951 impl ItemCanonicalPath for Item {
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>1952 fn namespace_aware_canonical_path(
1953 &self,
1954 ctx: &BindgenContext,
1955 ) -> Vec<String> {
1956 let mut path = self.canonical_path(ctx);
1957
1958 // ASSUMPTION: (disable_name_namespacing && cxx_namespaces)
1959 // is equivalent to
1960 // disable_name_namespacing
1961 if ctx.options().disable_name_namespacing {
1962 // Only keep the last item in path
1963 let split_idx = path.len() - 1;
1964 path = path.split_off(split_idx);
1965 } else if !ctx.options().enable_cxx_namespaces {
1966 // Ignore first item "root"
1967 path = vec![path[1..].join("_")];
1968 }
1969
1970 if self.is_constified_enum_module(ctx) {
1971 path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
1972 }
1973
1974 path
1975 }
1976
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>1977 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
1978 self.compute_path(ctx, UserMangled::Yes)
1979 }
1980 }
1981
1982 /// Whether to use the user-mangled name (mangled by the `item_name` callback or
1983 /// not.
1984 ///
1985 /// Most of the callers probably want just yes, but the ones dealing with
1986 /// allowlisting and blocklisting don't.
1987 #[derive(Copy, Clone, Debug, PartialEq)]
1988 enum UserMangled {
1989 No,
1990 Yes,
1991 }
1992
1993 /// Builder struct for naming variations, which hold inside different
1994 /// flags for naming options.
1995 #[derive(Debug)]
1996 pub(crate) struct NameOptions<'a> {
1997 item: &'a Item,
1998 ctx: &'a BindgenContext,
1999 within_namespaces: bool,
2000 user_mangled: UserMangled,
2001 }
2002
2003 impl<'a> NameOptions<'a> {
2004 /// Construct a new `NameOptions`
new(item: &'a Item, ctx: &'a BindgenContext) -> Self2005 pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
2006 NameOptions {
2007 item,
2008 ctx,
2009 within_namespaces: false,
2010 user_mangled: UserMangled::Yes,
2011 }
2012 }
2013
2014 /// Construct the name without the item's containing C++ namespaces mangled
2015 /// into it. In other words, the item's name within the item's namespace.
within_namespaces(&mut self) -> &mut Self2016 pub(crate) fn within_namespaces(&mut self) -> &mut Self {
2017 self.within_namespaces = true;
2018 self
2019 }
2020
user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self2021 fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self {
2022 self.user_mangled = user_mangled;
2023 self
2024 }
2025
2026 /// Construct a name `String`
get(&self) -> String2027 pub(crate) fn get(&self) -> String {
2028 self.item.real_canonical_name(self.ctx, self)
2029 }
2030 }
2031