Skip to content

Conversation

@kuecks
Copy link

@kuecks kuecks commented Jul 6, 2021

Added bindings to rust's std::option::Option, and C++'s std::optional::optional. Still a WIP but this is able to compile and run a simple example

Copy link

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only superficially skimmed this (and am not a reviewer here really) - mostly just wanted to say thanks for working on this! My codebase extensively uses Option<T> and this will be really nice to have.

Comment on lines 1 to 2
//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
//! itself is exposed at the crate root.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like copy-paste dup.

///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we can never obtain a `CxxOptional` by value. Instead in
/// Rust code we will only ever look at a vector behind a reference or smart

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/vector/optional/

@CAD97
Copy link
Contributor

CAD97 commented Aug 3, 2021

I just want to note that this (deliberately) conflicts with #868, in which I would like to have Option<&T>Rust translate to T const*C++ on the C++ side, rather than ::rust::Option<T const*>C++ as implemented here. This is specifically for binding to existing C++ APIs that accept T* as either a valid pointer or nullptr.

I also ran into the issue of Option<Pin<&mut T>> versus Pin<Option<&mut T>> and also of Option<Option<&T>> in that PR (Pin<Pin<&mut T>> is allowed today and normalizes to just Pin<&mut T>); so make sure that you don't have the same issue here. I don't think you do, since I modeled Option as part of the pointer type (like Pin) and you've modeled Option as a new kind of type (like Box), but it's worth double checking that nesting works properly.

@kuecks
Copy link
Author

kuecks commented Aug 24, 2021

I also ran into the issue of Option<Pin<&mut T>> versus Pin<Option<&mut T>> and also of Option<Option<&T>> in that PR (Pin<Pin<&mut T>> is allowed today and normalizes to just Pin<&mut T>); so make sure that you don't have the same issue here.

Thanks for mentioning Pin, I wasn't handling it at all and needed to add special case for it.

@kuecks
Copy link
Author

kuecks commented Aug 24, 2021

Notes: all the changes under demo/ will be reverted, that's just my playground. The code feels quire repetitive and nasty, but I can't figure out any better way, there's just so many subtly different cases :(. Also please let me know if you want me to break it up into multiple commits somehow for reviewability, this is quite massive.

let element = match inner {
OptionInner::RustBox(key) => RustOption::RustBox(key.rust),
OptionInner::Ref(key) => {
if out.types.try_resolve(key.rust).is_none() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check seems really hacky :/ The intent is that if this is a builtin type like u8, the implementations are already written (and trying to implement it here would violate orphan rules anyway) so just skip it. Is there a more straightforward way to check that?

}
}

impl<'a, T> RustOption<&'a T> {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some of these implementations can be removed but maybe its future proofing to have them? I can try to see which ones are unneeded

}
}

impl RustOption<crate::private::RustStr> {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seemed particularly sketchy

match self.try_resolve(ident) {
Some(resolution) => resolution,
None => panic!("Unable to resolve type `{}`", ident),
None => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrmm i think this should be reverted

tests/ffi/lib.rs Outdated
fn c_return_ref_optional(i: &u8) -> &CxxOptional<u8>;
fn c_return_mut_optional(i: &mut u8) -> &mut CxxOptional<u8>;
fn c_return_rust_option_box() -> Option<Box<Shared>>;
fn c_return_rust_ref_option_shared() -> Option<&'static Shared>;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs were by far the most complicated one so I tried to have extensive testing (which caught a lot of bugs). Are there any cases I missed?

@kuecks kuecks marked this pull request as ready for review August 25, 2021 17:06
@djpiper28
Copy link

Is this pr going anywhere? I am quite interested in this feature.

@kuecks
Copy link
Author

kuecks commented May 4, 2022

@djpiper28 yes I am still interested in pushing this through, I think dtolnay is (understandably) just quite busy unfortunately. I may explore alternative implementations, specifically reference_wrapper, in the meantime

@VirxEC
Copy link

VirxEC commented Dec 9, 2022

Any progress? This feature would be pretty big... what's blocking it?

@xdray
Copy link

xdray commented Mar 22, 2023

is anyone doing this?

@kuecks kuecks closed this by deleting the head repository Feb 28, 2024
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.

6 participants