From 1aa60eebc44e89ee31636c9a252c13e0fc81b0de Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Thu, 15 Jan 2026 03:15:33 -0800 Subject: [PATCH] Add the `Ctor!` convenience/abstraction macro we've talked about. The purpose of this macro is to hide the impl trait. This makes it easier to change over time, and makes the caller interface much easier to work with, requiring less mindless repetitive typing. We've said that a snippet of C++ should not require 5x as many tokens to type as the Rust equivalent when using Crubit. So specifying that you return a type, where in C++ it's `Foo`, in Rust it's `-> Ctor`. 1 token vs 16 tokens! This CL brings it down to `-> ctor::Ctor![Foo]`, 8 tokens. That's about as minimal as we can make it. (Fortunately I think the 5x rule was aimed at function calls, not defining functions, or we'd be in trouble!) Note that it doesn't work if you need `use<'a, Self>` and such. I tried, but that was really hard to parse if the macro is to have a really even remotely reasonable syntax. (It needs to support both lifetimes and types, and so on.) Instead, opted to just leave them out. They aren't necessary in Rust 2024. PiperOrigin-RevId: 856582885 --- docs/cpp/non_rust_movable.md | 14 +++-- docs/overview/unstable_features.md | 4 +- .../generate_bindings/generate_function.rs | 56 ++++++++++--------- .../generate_function_test.rs | 8 +-- .../test/golden/inheritance_rs_api.rs | 6 +- .../test/golden/no_unique_address_rs_api.rs | 4 +- .../test/golden/nontrivial_type_rs_api.rs | 36 ++++++------ .../test/golden/operators_rs_api.rs | 2 +- .../test/golden/polymorphic_rs_api.rs | 6 +- .../test/golden/unions_rs_api.rs | 2 +- .../test/golden/user_of_base_class_rs_api.rs | 4 +- .../test/golden/user_of_unsupported_rs_api.rs | 5 +- .../default_member_functions_rs_api.rs | 4 +- .../inheritance/inherited_methods_rs_api.rs | 14 ++--- .../wrapper/impl_ctor/impl_ctor_rs_api.rs | 10 ++-- support/ctor.rs | 40 ++++++++++--- 16 files changed, 119 insertions(+), 96 deletions(-) diff --git a/docs/cpp/non_rust_movable.md b/docs/cpp/non_rust_movable.md index 682837ec7..78f18a8c7 100644 --- a/docs/cpp/non_rust_movable.md +++ b/docs/cpp/non_rust_movable.md @@ -23,11 +23,12 @@ support/ctor.rs `Ctor` is a trait for implementing **lazily evaluated values**. These values are constructed in-place, in a C++-compatible way, and -pinned. +pinned. It is typically used as an `impl Ctor`, which is most +easily spelled as `Ctor![T]` or `Ctor![T, Error=...]`. -However, `Ctor` is not a lazily-initialized value itself. It is a value -initialization procedure, which returns `T` upon success and `E` upon failure. -So a `Ctor` creates a value upon request, which is why we describe it as lazy. +`Ctor` is not a lazily-initialized value itself. It is a value initialization +procedure, which returns `T` upon success and `E` upon failure. So a `Ctor` +creates a value upon request, which is why we describe it as lazy. Since exceptions are disabled at Google, we currently only work with `Error=Infallible`, and for exposition will omit the error type. @@ -36,8 +37,9 @@ Functions accepting and returning a non-Rust movable value in C++ will accept and return an `impl Ctor` in Rust, as so: ```rust -pub fn accepts_value(x: impl Ctor) {...} -pub fn returns() -> impl Ctor {...} +pub fn accepts_value(x: Ctor![CppType]) {...} +// equivalent to x: impl Ctor +pub fn returns() -> Ctor![CppType] {...} ``` The easiest way to work with these types in Rust is to box them into a diff --git a/docs/overview/unstable_features.md b/docs/overview/unstable_features.md index 76d0d7d6d..ab2c4841d 100644 --- a/docs/overview/unstable_features.md +++ b/docs/overview/unstable_features.md @@ -248,8 +248,8 @@ Instead, these objects support lazy construction, in the same style as results in, for example, the following API differences: `X` is rust-movable | `X` is not rust-movable --------------------- | --------------------------------------- -`pub fn foo() -> X` | `pub fn foo() -> impl Ctor` +-------------------- | ------------------------------------------ +`pub fn foo() -> X` | `pub fn foo() -> impl Ctor` `impl Add for &C` | `impl> Add for &C` The problem comes in with operator overloading: the following is valid: diff --git a/rs_bindings_from_cc/generate_bindings/generate_function.rs b/rs_bindings_from_cc/generate_bindings/generate_function.rs index 514b0934d..bb2957948 100644 --- a/rs_bindings_from_cc/generate_bindings/generate_function.rs +++ b/rs_bindings_from_cc/generate_bindings/generate_function.rs @@ -861,7 +861,7 @@ fn api_func_shape_for_constructor( /// Returns the shape of the generated Rust API for a given function definition. /// /// If the shape is a trait, this also mutates the parameter types to be -/// trait-compatible. In particular, types which would be `impl Ctor` +/// trait-compatible. In particular, types which would be `Ctor![T]` /// become a `RvalueReference<'_, T>`. /// /// Returns: @@ -1842,8 +1842,8 @@ struct BindingsSignature { /// The return type fragment of the Rust function, as a token stream. /// /// This is the same as the actual return type, except that () is the empty - /// tokens, non-Unpin by-value types are `impl Ctor + - /// ...`, and wherever the type is the type of `Self`, it gets replaced by + /// tokens, non-Unpin by-value types are `Ctor![#return_type] + ...`, + /// and wherever the type is the type of `Self`, it gets replaced by /// literal `Self`. return_type_fragment: TokenStream, @@ -1930,7 +1930,7 @@ fn function_signature( type_.to_token_stream_with_owned_ptr_type(db) }; *features |= Feature::impl_trait_in_assoc_type; - api_params.push(quote! {#ident: impl ::ctor::Ctor}); + api_params.push(quote! {#ident: ::ctor::Ctor![#quoted_type_or_self]}); thunk_args .push(quote! {::core::pin::Pin::into_inner_unchecked(::ctor::emplace!(#ident))}); } else { @@ -2040,31 +2040,37 @@ fn function_signature( Some(TraitName::Other { .. }) | None => {} } - let return_type_fragment = - if matches!(return_type.unalias(), RsTypeKind::Primitive(Primitive::Void)) { - quote! {} + let return_type_fragment = if matches!( + return_type.unalias(), + RsTypeKind::Primitive(Primitive::Void) + ) { + quote! {} + } else { + let ty = quoted_return_type + .unwrap_or_else(|| return_type.to_token_stream_with_owned_ptr_type(db)); + if return_type.is_unpin() { + ty } else { - let ty = quoted_return_type - .unwrap_or_else(|| return_type.to_token_stream_with_owned_ptr_type(db)); - if return_type.is_unpin() { - ty + // TODO(jeanpierreda): use `-> impl Ctor` instead of `-> Self::X` where `X = impl + // Ctor`. The latter requires `impl_trait_in_assoc_type`, the former + // was stabilized in 1.75. Directly returning an unnameable `impl + // Ctor` is sufficient for us, and makes traits like `CtorNew` more + // similar to top-level functions.) + + // The returned lazy FnCtor depends on all inputs. + let extra_lifetimes = if lifetimes.is_empty() { + quote! {} + } else { + quote! {+ use<#(#lifetimes),*> } + }; + *features |= Feature::impl_trait_in_assoc_type; + if extra_lifetimes.is_empty() { + quote! {::ctor::Ctor![#ty]} } else { - // TODO(jeanpierreda): use `-> impl Ctor` instead of `-> Self::X` where `X = impl - // Ctor`. The latter requires `impl_trait_in_assoc_type`, the former - // was stabilized in 1.75. Directly returning an unnameable `impl - // Ctor` is sufficient for us, and makes traits like `CtorNew` more - // similar to top-level functions.) - - // The returned lazy FnCtor depends on all inputs. - let extra_lifetimes = if lifetimes.is_empty() { - quote! {} - } else { - quote! {+ use<#(#lifetimes),*> } - }; - *features |= Feature::impl_trait_in_assoc_type; quote! {impl ::ctor::Ctor #extra_lifetimes } } - }; + } + }; // Change `__this: &'a SomeStruct` into `&'a self` if needed. if impl_kind.format_first_param_as_self() { diff --git a/rs_bindings_from_cc/generate_bindings/generate_function_test.rs b/rs_bindings_from_cc/generate_bindings/generate_function_test.rs index 97ebaf698..d567b54f2 100644 --- a/rs_bindings_from_cc/generate_bindings/generate_function_test.rs +++ b/rs_bindings_from_cc/generate_bindings/generate_function_test.rs @@ -1449,7 +1449,7 @@ fn test_nonunpin_0_arg_constructor() -> Result<()> { rs_api, quote! { impl ::ctor::CtorNew<()> for HasConstructor { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] @@ -1483,7 +1483,7 @@ fn test_nonunpin_1_arg_constructor() -> Result<()> { rs_api, quote! { impl ::ctor::CtorNew<::core::ffi::c_uchar> for HasConstructor { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline (always)] @@ -1517,7 +1517,7 @@ fn test_nonunpin_2_arg_constructor() -> Result<()> { rs_api, quote! { impl ::ctor::CtorNew<(::core::ffi::c_uchar, ::core::ffi::c_schar)> for HasConstructor { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline (always)] @@ -1876,7 +1876,7 @@ fn test_nonunpin_param() -> Result<()> { assert_rs_matches!( rs_api, quote! { - pub fn TakesByValue(x: impl ::ctor::Ctor) { + pub fn TakesByValue(x: ::ctor::Ctor![crate::Nontrivial]) { unsafe { crate::detail::__rust_thunk___Z12TakesByValue10Nontrivial(::core::pin::Pin::into_inner_unchecked(::ctor::emplace!(x))) } diff --git a/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs b/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs index 5f73dcefc..747e4551e 100644 --- a/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs @@ -215,7 +215,7 @@ unsafe impl ::cxx::ExternType for VirtualBase1 { } impl ::ctor::CtorNew<()> for VirtualBase1 { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -262,7 +262,7 @@ unsafe impl ::cxx::ExternType for VirtualBase2 { } impl ::ctor::CtorNew<()> for VirtualBase2 { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -309,7 +309,7 @@ unsafe impl ::cxx::ExternType for VirtualDerived { } impl ::ctor::CtorNew<()> for VirtualDerived { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/no_unique_address_rs_api.rs b/rs_bindings_from_cc/test/golden/no_unique_address_rs_api.rs index 296d3c9f6..e50a91b2f 100644 --- a/rs_bindings_from_cc/test/golden/no_unique_address_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/no_unique_address_rs_api.rs @@ -179,7 +179,7 @@ unsafe impl ::cxx::ExternType for FieldInTailPadding_InnerStruct { } impl ::ctor::CtorNew<()> for FieldInTailPadding_InnerStruct { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -264,7 +264,7 @@ impl ::ctor::PinnedDrop for FieldInTailPadding { // //rs_bindings_from_cc/test/golden:no_unique_address_cc needs [//features:experimental] for FieldInTailPadding::operator= (the type of __param_0 (parameter #1): references are not supported) impl ::ctor::CtorNew<(::ffi_11::c_int, ::ffi_11::c_char, ::ffi_11::c_char)> for FieldInTailPadding { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int, ::ffi_11::c_char, ::ffi_11::c_char)) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/nontrivial_type_rs_api.rs b/rs_bindings_from_cc/test/golden/nontrivial_type_rs_api.rs index 6e864068c..5800036b6 100644 --- a/rs_bindings_from_cc/test/golden/nontrivial_type_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/nontrivial_type_rs_api.rs @@ -58,7 +58,7 @@ impl Nontrivial { } impl ::ctor::CtorNew<()> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -72,7 +72,7 @@ impl ::ctor::CtorNew<()> for Nontrivial { } impl ::ctor::CtorNew<::ffi_11::c_int> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::ffi_11::c_int) -> Self::CtorType { @@ -88,7 +88,7 @@ impl ::ctor::CtorNew<::ffi_11::c_int> for Nontrivial { } } impl ::ctor::CtorNew<(::ffi_11::c_int,)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int,)) -> Self::CtorType { @@ -98,7 +98,7 @@ impl ::ctor::CtorNew<(::ffi_11::c_int,)> for Nontrivial { } impl ::ctor::CtorNew<(::ffi_11::c_int, ::ffi_11::c_int)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int, ::ffi_11::c_int)) -> Self::CtorType { @@ -210,7 +210,7 @@ impl NontrivialInline { } impl ::ctor::CtorNew<()> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -226,7 +226,7 @@ impl ::ctor::CtorNew<()> for NontrivialInline { } impl ::ctor::CtorNew<::ffi_11::c_int> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::ffi_11::c_int) -> Self::CtorType { @@ -242,7 +242,7 @@ impl ::ctor::CtorNew<::ffi_11::c_int> for NontrivialInline { } } impl ::ctor::CtorNew<(::ffi_11::c_int,)> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int,)) -> Self::CtorType { @@ -252,7 +252,7 @@ impl ::ctor::CtorNew<(::ffi_11::c_int,)> for NontrivialInline { } impl ::ctor::CtorNew<(::ffi_11::c_int, ::ffi_11::c_int)> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int, ::ffi_11::c_int)) -> Self::CtorType { @@ -319,7 +319,7 @@ unsafe impl ::cxx::ExternType for NontrivialMembers { } impl ::ctor::CtorNew<()> for NontrivialMembers { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -447,8 +447,8 @@ impl Drop for NontrivialUnpin { #[inline(always)] pub fn TakesByValue( - nontrivial: impl ::ctor::Ctor, -) -> impl ::ctor::Ctor { + nontrivial: ::ctor::Ctor![crate::Nontrivial], +) -> ::ctor::Ctor![crate::Nontrivial] { unsafe { ::ctor::FnCtor::new(move |dest: *mut crate::Nontrivial| { crate::detail::__rust_thunk___Z12TakesByValue10Nontrivial( @@ -461,8 +461,8 @@ pub fn TakesByValue( #[inline(always)] pub fn TakesByValueInline( - nontrivial: impl ::ctor::Ctor, -) -> impl ::ctor::Ctor { + nontrivial: ::ctor::Ctor![crate::NontrivialInline], +) -> ::ctor::Ctor![crate::NontrivialInline] { unsafe { ::ctor::FnCtor::new(move |dest: *mut crate::NontrivialInline| { crate::detail::__rust_thunk___Z18TakesByValueInline16NontrivialInline( @@ -612,7 +612,7 @@ impl Nonmovable { } impl ::ctor::CtorNew<()> for Nonmovable { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -637,9 +637,8 @@ impl ::ctor::PinnedDrop for Nonmovable { )] pub trait BindingFailedFor_Z22TakesNonmovableByValue10Nonmovable {} #[inline(always)] -pub fn TakesNonmovableByValue<'error>( - nonmovable: impl ::ctor::Ctor, -) where +pub fn TakesNonmovableByValue<'error>(nonmovable: ::ctor::Ctor![crate::Nonmovable]) +where &'error (): BindingFailedFor_Z22TakesNonmovableByValue10Nonmovable, { #![allow(unused_variables)] @@ -650,8 +649,7 @@ pub fn TakesNonmovableByValue<'error>( } #[inline(always)] -pub fn ReturnsNonmovableByValue( -) -> impl ::ctor::Ctor { +pub fn ReturnsNonmovableByValue() -> ::ctor::Ctor![crate::Nonmovable] { unsafe { ::ctor::FnCtor::new(move |dest: *mut crate::Nonmovable| { crate::detail::__rust_thunk___Z24ReturnsNonmovableByValuev( diff --git a/rs_bindings_from_cc/test/golden/operators_rs_api.rs b/rs_bindings_from_cc/test/golden/operators_rs_api.rs index 6edb5343e..31797946c 100644 --- a/rs_bindings_from_cc/test/golden/operators_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/operators_rs_api.rs @@ -529,7 +529,7 @@ unsafe impl ::cxx::ExternType for AddableConstMemberNonunpin { } impl ::ctor::CtorNew<()> for AddableConstMemberNonunpin { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/polymorphic_rs_api.rs b/rs_bindings_from_cc/test/golden/polymorphic_rs_api.rs index 8f74c515e..883425921 100644 --- a/rs_bindings_from_cc/test/golden/polymorphic_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/polymorphic_rs_api.rs @@ -34,7 +34,7 @@ unsafe impl ::cxx::ExternType for PolymorphicBase { } impl ::ctor::CtorNew<()> for PolymorphicBase { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -85,7 +85,7 @@ impl PolymorphicBase2 { } impl ::ctor::CtorNew<()> for PolymorphicBase2 { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -130,7 +130,7 @@ unsafe impl ::cxx::ExternType for PolymorphicDerived { } impl ::ctor::CtorNew<()> for PolymorphicDerived { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/unions_rs_api.rs b/rs_bindings_from_cc/test/golden/unions_rs_api.rs index c3f08f72d..e1aa469ef 100644 --- a/rs_bindings_from_cc/test/golden/unions_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/unions_rs_api.rs @@ -77,7 +77,7 @@ unsafe impl ::cxx::ExternType for Nontrivial { } impl ::ctor::CtorNew<()> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs index 26692267b..cfa33c259 100644 --- a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs @@ -40,7 +40,7 @@ unsafe impl ::cxx::ExternType for Derived2 { } impl ::ctor::CtorNew<()> for Derived2 { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -85,7 +85,7 @@ unsafe impl ::cxx::ExternType for VirtualDerived2 { } impl ::ctor::CtorNew<()> for VirtualDerived2 { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/golden/user_of_unsupported_rs_api.rs b/rs_bindings_from_cc/test/golden/user_of_unsupported_rs_api.rs index 634708f7e..46c123fee 100644 --- a/rs_bindings_from_cc/test/golden/user_of_unsupported_rs_api.rs +++ b/rs_bindings_from_cc/test/golden/user_of_unsupported_rs_api.rs @@ -16,10 +16,7 @@ #[inline(always)] pub fn UseNontrivialCustomType( - non_trivial_custom_type: impl ::ctor::Ctor< - Output = ::unsupported_cc::NontrivialCustomType, - Error = ::ctor::Infallible, - >, + non_trivial_custom_type: ::ctor::Ctor![::unsupported_cc::NontrivialCustomType], ) { unsafe { crate::detail::__rust_thunk___Z23UseNontrivialCustomType20NontrivialCustomType( diff --git a/rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions_rs_api.rs b/rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions_rs_api.rs index 3e216b2e8..63b6e6623 100644 --- a/rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions_rs_api.rs +++ b/rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions_rs_api.rs @@ -37,7 +37,7 @@ unsafe impl ::cxx::ExternType for Uncopyable { /// Generated from: rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions.h;l=12 impl ::ctor::CtorNew<()> for Uncopyable { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -81,7 +81,7 @@ impl ::ctor::PinnedDrop for UncopyableDespiteDecl { /// Generated from: rs_bindings_from_cc/test/struct/default_member_functions/default_member_functions.h;l=19 impl ::ctor::CtorNew<()> for UncopyableDespiteDecl { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { diff --git a/rs_bindings_from_cc/test/struct/inheritance/inherited_methods_rs_api.rs b/rs_bindings_from_cc/test/struct/inheritance/inherited_methods_rs_api.rs index e6cb9b74f..1bd749baa 100644 --- a/rs_bindings_from_cc/test/struct/inheritance/inherited_methods_rs_api.rs +++ b/rs_bindings_from_cc/test/struct/inheritance/inherited_methods_rs_api.rs @@ -38,7 +38,7 @@ forward_declare::unsafe_define!(forward_declare::symbol!("Nonmovable"), crate::N /// Generated from: rs_bindings_from_cc/test/struct/inheritance/inherited_methods.h;l=11 impl ::ctor::CtorNew<()> for Nonmovable { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ()) -> Self::CtorType { @@ -73,10 +73,8 @@ impl Base { } /// Generated from: rs_bindings_from_cc/test/struct/inheritance/inherited_methods.h;l=19 #[inline(always)] - pub fn no_bindings<'error, 'a>( - &'a self, - __param_0: impl ::ctor::Ctor, - ) where + pub fn no_bindings<'error, 'a>(&'a self, __param_0: ::ctor::Ctor![crate::Nonmovable]) + where &'error (): BindingFailedFor_ZNK4Base11no_bindingsE10Nonmovable, { #![allow(unused_variables)] @@ -128,10 +126,8 @@ impl Derived { } /// Generated from: rs_bindings_from_cc/test/struct/inheritance/inherited_methods.h;l=19 #[inline(always)] - pub fn no_bindings<'error, 'a>( - &'a self, - __param_0: impl ::ctor::Ctor, - ) where + pub fn no_bindings<'error, 'a>(&'a self, __param_0: ::ctor::Ctor![crate::Nonmovable]) + where &'error (): BindingFailedFor_7Derived__ZNK4Base11no_bindingsE10Nonmovable, { #![allow(unused_variables)] diff --git a/rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor_rs_api.rs b/rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor_rs_api.rs index c39df14cf..9b42555cc 100644 --- a/rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor_rs_api.rs +++ b/rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor_rs_api.rs @@ -39,7 +39,7 @@ forward_declare::unsafe_define!(forward_declare::symbol!("Nontrivial"), crate::N /// Generated from: rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor.h;l=10 impl ::ctor::CtorNew<::ffi_11::c_int> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::ffi_11::c_int) -> Self::CtorType { @@ -55,7 +55,7 @@ impl ::ctor::CtorNew<::ffi_11::c_int> for Nontrivial { } } impl ::ctor::CtorNew<(::ffi_11::c_int,)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::ffi_11::c_int,)) -> Self::CtorType { @@ -111,7 +111,7 @@ impl ::ctor::PinnedDrop for Nontrivial { /// Generated from: rs_bindings_from_cc/test/wrapper/impl_ctor/impl_ctor.h;l=16 #[inline(always)] -pub fn Create() -> impl ::ctor::Ctor { +pub fn Create() -> ::ctor::Ctor![crate::Nontrivial] { unsafe { ::ctor::FnCtor::new(move |dest: *mut crate::Nontrivial| { crate::detail::__rust_thunk___Z6Createv(dest as *mut ::core::ffi::c_void); @@ -121,9 +121,7 @@ pub fn Create() -> impl ::ctor::Ctor, -) -> ::ffi_11::c_int { +pub fn Read(nontrivial: ::ctor::Ctor![crate::Nontrivial]) -> ::ffi_11::c_int { unsafe { crate::detail::__rust_thunk___Z4Read10Nontrivial(::core::pin::Pin::into_inner_unchecked( ::ctor::emplace!(nontrivial), diff --git a/support/ctor.rs b/support/ctor.rs index aecfd7e88..0c95f98ee 100644 --- a/support/ctor.rs +++ b/support/ctor.rs @@ -188,6 +188,9 @@ macro_rules! must_use_ctor_assign { /// In-place initialization of a value. /// +/// This is commonly used as `impl Ctor`, in function parameters or +/// return types, and can be spelled `Ctor![T]`. +/// /// # Safety /// /// Implementations must satisfy the postconditions of the `ctor` method. @@ -215,7 +218,7 @@ pub unsafe trait Ctor: Sized { /// /// This is useful for chaining possibly-fallible operations (such as `ctor_then`) on top of /// an existing infallible `Ctor`. - fn ctor_make_fallible(self) -> impl Ctor + fn ctor_make_fallible(self) -> Ctor![Self::Output, Error = E] where Self: Ctor, { @@ -223,7 +226,7 @@ pub unsafe trait Ctor: Sized { } /// Maps this `Ctor`'s error type into a new error type using the `Into` trait. - fn ctor_err_into(self) -> impl Ctor + fn ctor_err_into(self) -> Ctor![Self::Output, Error = E] where Self::Error: Into, { @@ -248,7 +251,7 @@ pub unsafe trait Ctor: Sized { /// }); /// let x = emplace!(new_ctor); /// ``` - fn ctor_then(self, f: F) -> impl Ctor + fn ctor_then(self, f: F) -> Ctor![Self::Output, Error = Self::Error] where F: FnOnce(Pin<&mut Self::Output>) -> Result<(), Self::Error>, { @@ -296,7 +299,7 @@ pub unsafe trait Ctor: Sized { /// let new_ctor = y.ctor_map_err(|e| e.into_new_error()); /// let x = try_emplace!(new_ctor); /// ``` - fn ctor_map_err(self, f: F) -> impl Ctor + fn ctor_map_err(self, f: F) -> Ctor![Self::Output, Error = E] where F: FnOnce(Self::Error) -> E, { @@ -314,7 +317,7 @@ pub unsafe trait Ctor: Sized { /// let new_ctor = Y::first_attempt().ctor_or_else(|_| Y::fallback_attempt()); /// let x = try_emplace!(new_ctor); /// ``` - fn ctor_or_else(self, f: F) -> impl Ctor + fn ctor_or_else(self, f: F) -> Ctor![Self::Output, Error = O::Error] where F: FnOnce(Self::Error) -> O, O: Ctor, @@ -374,7 +377,7 @@ pub unsafe trait Ctor: Sized { /// Returns a `Ctor` which will panic if the original construction fails. /// /// This functions similarly to `Result::unwrap`. - fn ctor_unwrap(self) -> impl Ctor + fn ctor_unwrap(self) -> Ctor![Self::Output, Error = Infallible] where Self::Error: Debug, { @@ -393,7 +396,7 @@ pub unsafe trait Ctor: Sized { /// This functions similarly to `Result::unwrap_or_default`. fn ctor_unwrap_or_default( self, - ) -> impl Ctor>::Error> + ) -> Ctor![Self::Output, Error = >::Error] where Self::Output: CtorNew<()>, { @@ -401,6 +404,28 @@ pub unsafe trait Ctor: Sized { } } +/// The type macro for an `impl Ctor<...>`, used as a parameter or return type. +/// +/// This exists for two reasons: +/// +/// 1. To allow for changing the implementation over time. +/// 2. To make the spelling less overly verbose. Instead of `impl Ctor`, +/// you can write `Ctor![T]`. +/// +/// In codebases not yet migrated to the 2024 edition, if you need a `use<'a>` bound, you must +/// write the full `impl` syntax: `impl Ctor + use<'a, 'b>`. +/// +/// (It is surprisingly difficult to write a macro that would allow the `use` parameters!) +#[macro_export] +macro_rules! Ctor { + ( $T:ty $(,)? ) => { + impl $crate::Ctor + }; + ( $T:ty, Error = $E:ty $(,)? ) => { + impl $crate::Ctor + }; +} + /// Returns a `Ctor` with error type `E` which always fails with the given error. pub fn ctor_error(e: E) -> impl Ctor { struct CtorError { @@ -1028,6 +1053,7 @@ impl Slot { #[doc(hidden)] pub mod macro_internal { use super::*; + pub use crate::Infallible; pub use core::mem::MaybeUninit; pub use core::pin::Pin;