Skip to content

Conversation

@mini-1235
Copy link

Description

  • Add static assert for removed subscription callback signatures

Fixes #2972

Is this user-facing behavior change?

Yes

Did you use Generative AI?

No

Additional Information

When working on this PR, I noticed that #1713 only deprecates MessageT. However, looking at the comment here:

// Deprecated signatures:
using SharedPtrCallback =
std::function<void (std::shared_ptr<SubscribedType>)>;
using SharedPtrROSMessageCallback =
std::function<void (std::shared_ptr<ROSMessageType>)>;
using SharedPtrWithInfoCallback =
std::function<void (std::shared_ptr<SubscribedType>, const rclcpp::MessageInfo &)>;
using SharedPtrWithInfoROSMessageCallback =
std::function<void (
std::shared_ptr<ROSMessageType>,
const rclcpp::MessageInfo &)>;
using SharedPtrSerializedMessageCallback =
std::function<void (std::shared_ptr<rclcpp::SerializedMessage>)>;
using SharedPtrSerializedMessageWithInfoCallback =
std::function<void (std::shared_ptr<rclcpp::SerializedMessage>, const rclcpp::MessageInfo &)>;

it looks like the type_adaptation/serialized message are not yet deprecated, how should we proceed?

In the meantime, I have also updated the tests for type_adaptation/serialized to use std::shared_ptr<const>

Signed-off-by: mini-1235 <mauricepurnawan@gmail.com>
@mini-1235
Copy link
Author

mini-1235 commented Nov 9, 2025

I have pulled and built the ROS2 repos from https://raw.githubusercontent.com/ros2/ros2/rolling/ros2.repos (Please let me know if there are any other repos I should include)

Removing std::shared_ptr<MessageT> would have an impact on:

Removing/Deprecating std::shared_ptr<TypeAdapter/Serialize Message> would affect:

Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

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

@mini-1235 thanks for fixing up all the related packages and repositories.

changing signatures are totally fine things to do including this PR, but i want to discuss with you on either we should enforcement or deprecation here for the next release.

Comment on lines 420 to 422
static_assert(!is_invalid_signature,
"std::shared_ptr<> callback signature is unsupported "
"Use std::shared_ptr<const> or std::unique_ptr<> instead.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is true that those signatures have been deprecated for a long time as comment states, but my concern is that can we really enforce this all the sudden? i understand this is right thing to do, but this can possibly break the user space without any notification.

IMO, Deprecation Period should still be given for user space for next release, and then we can enforce the invalid signature assertion?

@mini-1235 @mjcarroll @ahcorde what do you think?

Copy link
Author

@mini-1235 mini-1235 Nov 11, 2025

Choose a reason for hiding this comment

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

I think there are two points to discuss here:

  1. std::shared_ptr<MessageT>: this was deprecated back in August 2021, but the deprecation warning was accidentally removed in February 2024. It looks like the majority of the ROS 2 core repositories are fine, but I am not entirely sure about other packages. For example, Nav2 still uses std::shared_ptr<MessageT> a lot: mini-1235/navigation2@9a6aca5

  2. std::shared_ptr<TypeAdapter/Serialize Message>: this signature was actually never deprecated, so I think it should be deprecated instead of removed

In my current PR, I removed all forms of std::shared_ptr<> mainly for testing purposes. I am open to any suggestions on how this should be handled :)

Copy link
Member

Choose a reason for hiding this comment

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

Do you have a link to the commit that removed the deprecation?

We could re-deprecate it, just to be safe, and add the static asserts after a cycle.

I'm actually curious what the shared_ptr<T> does right now. I guess it must be taking a copy (e.g. as a unique_ptr<T>) and making a new shared_ptr<T> for each callback?

Copy link
Author

Choose a reason for hiding this comment

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

Do you have a link to the commit that removed the deprecation?

#2431

We could re-deprecate it, just to be safe, and add the static asserts after a cycle.

OK!

I'm actually curious what the shared_ptr does right now. I guess it must be taking a copy (e.g. as a unique_ptr) and making a new shared_ptr for each callback?

I haven't had time to look into the implementation deeply yet, so I can only speak based on the experiments I have run so far. With intra-process communication enabled, I am seeing that for n subscribers, there are n-1 copies made

Signed-off-by: mini-1235 <mauricepurnawan@gmail.com>
@mini-1235
Copy link
Author

I am not sure how to deal with the deprecated tests here

void shared_ptr_ta_free_func(std::shared_ptr<MyEmpty>) {}
void shared_ptr_ta_w_info_free_func(
std::shared_ptr<MyEmpty>, const rclcpp::MessageInfo &)
{}
INSTANTIATE_TEST_SUITE_P(
SharedPtrCallbackTests,
DispatchTestsWithTA,
::testing::Values(
// lambda
InstanceContext<MyTA>{"lambda_ta", rclcpp::AnySubscriptionCallback<MyTA>().set(
[](std::shared_ptr<MyEmpty>) {})},
InstanceContext<MyTA>{"lambda_ta_with_info",
rclcpp::AnySubscriptionCallback<MyTA>().set(
[](std::shared_ptr<MyEmpty>, const rclcpp::MessageInfo &) {})},
InstanceContext<MyTA>{"lambda", rclcpp::AnySubscriptionCallback<MyTA>().set(
[](std::shared_ptr<test_msgs::msg::Empty>) {})},
InstanceContext<MyTA>{"lambda_with_info",
rclcpp::AnySubscriptionCallback<MyTA>().set(
[](std::shared_ptr<test_msgs::msg::Empty>, const rclcpp::MessageInfo &) {})},
// free function
InstanceContext<MyTA>{"free_function_ta", rclcpp::AnySubscriptionCallback<MyTA>().set(
shared_ptr_ta_free_func)},
InstanceContext<MyTA>{"free_function_ta_with_info",
rclcpp::AnySubscriptionCallback<MyTA>().set(
shared_ptr_ta_w_info_free_func)},
InstanceContext<MyTA>{"free_function", rclcpp::AnySubscriptionCallback<MyTA>().set(
shared_ptr_free_func)},
InstanceContext<MyTA>{"free_function_with_info",
rclcpp::AnySubscriptionCallback<MyTA>().set(
shared_ptr_w_info_free_func)},
// bind function
BindContext<MyTA, std::shared_ptr<MyEmpty>>("bind_method_ta"),
BindContext<MyTA, std::shared_ptr<MyEmpty>, const rclcpp::MessageInfo &>(
"bind_method_ta_with_info"),
BindContext<MyTA, std::shared_ptr<test_msgs::msg::Empty>>("bind_method"),
BindContext<MyTA, std::shared_ptr<test_msgs::msg::Empty>, const rclcpp::MessageInfo &>(
"bind_method_with_info")
),
format_parameter_with_ta
);

Should I add #define RCLCPP_AVOID_DEPRECATIONS_FOR_UNIT_TESTS 1 like the previous PR or any other better approach?

@mini-1235 mini-1235 changed the title Add static assert for removed subscription callback signatures Deprecate the shared_ptr<MessageT> subscription callback signatures Nov 27, 2025
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.

Deprecated subscription callback signatures are still compiling

3 participants