From aaa0b5594eb0ca715b85977ea7fc486ea64b287d Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Mon, 8 Dec 2025 16:40:55 -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: 841962605 --- docs/cpp/non_rust_movable.md | 14 +++-- docs/overview/unstable_features.md | 2 +- .../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 | 12 +--- .../wrapper/impl_ctor/impl_ctor_rs_api.rs | 10 ++-- support/ctor.rs | 41 +++++++++++--- 16 files changed, 117 insertions(+), 95 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..ee9edf442 100644 --- a/docs/overview/unstable_features.md +++ b/docs/overview/unstable_features.md @@ -249,7 +249,7 @@ 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() -> 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 569a1c7fc..f1d8c152e 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: @@ -1838,8 +1838,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, @@ -1926,7 +1926,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 { @@ -2036,31 +2036,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 91e5023eb..1152dd212 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 b6d138562..b05082382 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 @@ -181,7 +181,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 { @@ -268,7 +268,7 @@ impl ::ctor::PinnedDrop for FieldInTailPadding { impl ::ctor::CtorNew<(::core::ffi::c_int, ::core::ffi::c_char, ::core::ffi::c_char)> for FieldInTailPadding { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new( 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 5baeedef9..11e1088fc 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 @@ -40,7 +40,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 { @@ -54,7 +54,7 @@ impl ::ctor::CtorNew<()> for Nontrivial { } impl ::ctor::CtorNew<::core::ffi::c_int> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::core::ffi::c_int) -> Self::CtorType { @@ -70,7 +70,7 @@ impl ::ctor::CtorNew<::core::ffi::c_int> for Nontrivial { } } impl ::ctor::CtorNew<(::core::ffi::c_int,)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::core::ffi::c_int,)) -> Self::CtorType { @@ -80,7 +80,7 @@ impl ::ctor::CtorNew<(::core::ffi::c_int,)> for Nontrivial { } impl ::ctor::CtorNew<(::core::ffi::c_int, ::core::ffi::c_int)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::core::ffi::c_int, ::core::ffi::c_int)) -> Self::CtorType { @@ -214,7 +214,7 @@ unsafe impl ::cxx::ExternType for 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 { @@ -230,7 +230,7 @@ impl ::ctor::CtorNew<()> for NontrivialInline { } impl ::ctor::CtorNew<::core::ffi::c_int> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::core::ffi::c_int) -> Self::CtorType { @@ -246,7 +246,7 @@ impl ::ctor::CtorNew<::core::ffi::c_int> for NontrivialInline { } } impl ::ctor::CtorNew<(::core::ffi::c_int,)> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::core::ffi::c_int,)) -> Self::CtorType { @@ -256,7 +256,7 @@ impl ::ctor::CtorNew<(::core::ffi::c_int,)> for NontrivialInline { } impl ::ctor::CtorNew<(::core::ffi::c_int, ::core::ffi::c_int)> for NontrivialInline { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::core::ffi::c_int, ::core::ffi::c_int)) -> Self::CtorType { @@ -330,7 +330,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 { @@ -459,8 +459,8 @@ impl 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( @@ -473,8 +473,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( @@ -618,7 +618,7 @@ unsafe impl ::cxx::ExternType for 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 { @@ -650,9 +650,8 @@ impl 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)] @@ -663,8 +662,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 d045a061e..c732ac19e 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 9e1a7d971..00aee4d94 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 { @@ -79,7 +79,7 @@ unsafe impl ::cxx::ExternType for 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 { @@ -131,7 +131,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 c0b6734f1..f21d6ff9a 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 baa4f2bbb..5e721db6f 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 a86de1678..b296fb332 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 ef5e6c1ae..5e03aa77b 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 { @@ -96,10 +96,7 @@ where { /// Generated from: rs_bindings_from_cc/test/struct/inheritance/inherited_methods.h;l=19 #[inline(always)] - pub fn no_bindings<'a>( - &'a self, - __param_0: impl ::ctor::Ctor, - ) { + pub fn no_bindings<'a>(&'a self, __param_0: ::ctor::Ctor![crate::Nonmovable]) { #![allow(unused_variables)] unreachable!( "This impl can never be instantiated. \ @@ -155,10 +152,7 @@ where { /// Generated from: rs_bindings_from_cc/test/struct/inheritance/inherited_methods.h;l=19 #[inline(always)] - pub fn no_bindings<'a>( - &'a self, - __param_0: impl ::ctor::Ctor, - ) { + pub fn no_bindings<'a>(&'a self, __param_0: ::ctor::Ctor![crate::Nonmovable]) { #![allow(unused_variables)] unreachable!( "This impl can never be instantiated. \ 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 1f5db6098..6645ab24c 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<::core::ffi::c_int> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: ::core::ffi::c_int) -> Self::CtorType { @@ -55,7 +55,7 @@ impl ::ctor::CtorNew<::core::ffi::c_int> for Nontrivial { } } impl ::ctor::CtorNew<(::core::ffi::c_int,)> for Nontrivial { - type CtorType = impl ::ctor::Ctor; + type CtorType = ::ctor::Ctor![Self]; type Error = ::ctor::Infallible; #[inline(always)] fn ctor_new(args: (::core::ffi::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, -) -> ::core::ffi::c_int { +pub fn Read(nontrivial: ::ctor::Ctor![crate::Nontrivial]) -> ::core::ffi::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 b8e450d80..58342fcad 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,29 @@ 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 +1054,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;