Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap template and opaque types in a marker. #3151

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

adetaylor
Copy link
Contributor

As standard, bindgen treats C++ pointers and references the same in its output. Downstream postprocessors might want to treat these things differently; for example to use a CppRef type for C++ references to encode the fact that they're not (usually) null.

This PR emits references wrapped in a newtype wrapper called
bindgen_marker_Reference
This behavior is enabled by an option flag; it isn't default. This type isn't actually defined in bindgen; users are expected to define or replace this during postprocessing (e.g. by using syn to reinterpret bindgen's output, or perhaps there are ways to make this useful using --raw-line or other means to inject a transparent newtype wrapper).

The same approach is taken to types which bindgen chooses to make opaque. This is done in various circumstances but the most common case is for non-type template parameters.

Alternative designs considered:

  • Apply an attribute to the function taking or returning such a param, e.g. #[bindgen_marker_takes_reference_arg(1)] fn takes_reference(a: u32, b: *const Foo) This avoids the marker type, but the problem here is a more invasive change to bindgen because type information can no longer be contained in a syn::Type; type metadata needs to be communicated around inside bindgen.

  • Make a ParseCallbacks call each time a type is opaque or a reference. This would work for standalone opaque types, e.g. pub struct Bar { pub _bindgen_opaque_blob: u8 } but the main case where we need these is where bindgen is using an opaque or reference type in the signature of some function, and there's no real opportunity to describe this in any kind of callback, since the callback would have to describe where exactly in the function signature the opaque or reference type has been used (and then we run into the same problems of passing this metadata around in the innards of bindgen).

In order to maintain the current simple design where any C++ type is represented as a simple syn::Type, the best approach seems to be to do this wrapping in a fake marker type.

Another design decision here was to represent an RValue reference as:
TypeKind::Reference(, ReferenceKind::RValue)
rather than a new variant:
TypeKind::RValueReference(
)
In the majority of cases references are treated the same way whether they're rvalue or lvalue, so this was less invasive, but either is fine.

Part of google/autocxx#124

@adetaylor adetaylor mentioned this pull request Feb 24, 2025
8 tasks
As standard, bindgen treats C++ pointers and references the same in its
output. Downstream postprocessors might want to treat these things
differently; for example to use a CppRef<T> type for C++ references
to encode the fact that they're not (usually) null.

This PR emits references wrapped in a newtype wrapper called
  bindgen_marker_Reference<T>
This behavior is enabled by an option flag; it isn't default.
This type isn't actually defined in bindgen; users are expected
to define or replace this during postprocessing (e.g. by using
syn to reinterpret bindgen's output, or perhaps there are ways
to make this useful using --raw-line or other means to inject
a transparent newtype wrapper).

The same approach is taken to types which bindgen chooses to make
opaque. This is done in various circumstances but the most common
case is for non-type template parameters.

Alternative designs considered:
* Apply an attribute to the function taking or returning
  such a param, e.g.
    #[bindgen_marker_takes_reference_arg(1)]
    fn takes_reference(a: u32, b: *const Foo)
  This avoids the marker type, but the problem here is a
  more invasive change to bindgen because type information
  can no longer be contained in a syn::Type; type metadata
  needs to be communicated around inside bindgen.

* Make a ParseCallbacks call each time a type is opaque
  or a reference. This would work for standalone opaque types,
  e.g.
    pub struct Bar {
     pub _bindgen_opaque_blob: u8
    }
  but the main case where we need these is where bindgen is
  using an opaque or reference type in the signature of some
  function, and there's no real opportunity to describe this
  in any kind of callback, since the callback would have to
  describe where exactly in the function signature the
  opaque or reference type has been used (and then we run into
  the same problems of passing this metadata around in the
  innards of bindgen).

In order to maintain the current simple design where any C++
type is represented as a simple syn::Type, the best approach
seems to be to do this wrapping in a fake marker type.

Another design decision here was to represent an RValue
reference as:
  TypeKind::Reference(_, ReferenceKind::RValue)
rather than a new variant:
  TypeKind::RValueReference(_)
In the majority of cases references are treated the same way
whether they're rvalue or lvalue, so this was less invasive,
but either is fine.

Part of google/autocxx#124
@adetaylor adetaylor force-pushed the opaque-and-reference-annotations branch from 744fcca to 72a39cf Compare February 24, 2025 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant