From 238cb0919812cda5c5070f66d24cd9e3816ad097 Mon Sep 17 00:00:00 2001 From: Michael VanBemmel Date: Tue, 24 Feb 2026 15:29:54 -0800 Subject: [PATCH] Categorize functions by param/return Rust movability in item reports This is split into one flag for the presence of a non-Rust-movable C++ type by value and one flag for the presence of a non-Rust-movable C++ type by pointer (or reference), which will have different levels of API friction at the Rust call site. PiperOrigin-RevId: 874818309 --- common/error_report.rs | 10 ++++++++++ .../generate_bindings/generate_function.rs | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/common/error_report.rs b/common/error_report.rs index 02cd9c6c0..28bdd3675 100644 --- a/common/error_report.rs +++ b/common/error_report.rs @@ -218,6 +218,16 @@ pub enum Category { /// /// As an example, the C++ items `struct Foo{ T* x};` and `void Foo(T* x);` are unsafe. Unsafe = 1 << 9, + + // TODO: Sync past cramertj@'s integer constant CL to get 1 << 10. + // + /// This item is a C++ function with a return type or at least one parameter type that is + /// non-Rust-movable and passed by value. + NonMovableByValue = 1 << 11, + + /// This item is a C++ function with a return type or at least one parameter type that is + /// non-Rust-movable and passed by (potentially nested) pointer or reference. + NonMovableByRef = 1 << 12, // TODO(b/468093766): Abstract? base classes, public inheritance } diff --git a/rs_bindings_from_cc/generate_bindings/generate_function.rs b/rs_bindings_from_cc/generate_bindings/generate_function.rs index c7cd13017..00e5b337a 100644 --- a/rs_bindings_from_cc/generate_bindings/generate_function.rs +++ b/rs_bindings_from_cc/generate_bindings/generate_function.rs @@ -1473,6 +1473,24 @@ pub fn generate_function( let param_value_adjustments = adjust_param_types_for_trait_impl(db, &impl_kind, &mut param_types, &errors); + // Categorize the Rust-movability of the return type and parameter types. + for mut ty in std::iter::once(&return_type).chain(param_types.iter()) { + // Note that pointers and references are Unpin, so this only fires for value types. + if !ty.is_unpin() { + db.errors().add_category(error_report::Category::NonMovableByValue); + } + + // Traverse all the way through any pointers or references to the underlying value type. + let mut was_ref = false; + while let Some(referent) = ty.referent() { + ty = referent; + was_ref = true; + } + if was_ref && !ty.is_unpin() { + db.errors().add_category(error_report::Category::NonMovableByRef); + } + } + // TODO(b/454627672): Possibly amend the logic around lifetime binding here for // assume_lifetimes.