Skip to content

Manually cast heapless::Vec to slice for select_slice#898

Open
RobertZ2011 wants to merge 1 commit into
OpenDevicePartnership:mainfrom
RobertZ2011:manually-cast-pins
Open

Manually cast heapless::Vec to slice for select_slice#898
RobertZ2011 wants to merge 1 commit into
OpenDevicePartnership:mainfrom
RobertZ2011:manually-cast-pins

Conversation

@RobertZ2011

@RobertZ2011 RobertZ2011 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

The current implementation of pin! automatically does type coercion with references. We rely on this when using select_slice. However, this behavior is unsound because there's no guarantee that the result of this coercion is actually pinned. Pre-emptively Use map_unchecked_mut to manually perform this cast since it is safe in our case and because this fix will eventually land on main (currently present on nightly 1.97).

See rust-lang/rust#153438 and rust-lang/rust#153457.

@RobertZ2011 RobertZ2011 self-assigned this Jun 18, 2026
@RobertZ2011 RobertZ2011 force-pushed the manually-cast-pins branch 2 times, most recently from eda635e to 9013e23 Compare June 18, 2026 18:44
@RobertZ2011 RobertZ2011 requested a review from Copilot June 18, 2026 18:44
The current implementation of `pin!` automatically does type coercion
with references. We rely on this when using `select_slice`. However, this
behavior is unsound because there's no guarantee that the result of
this coercion is actually pinned. Pre-emptively Use `map_unchecked_mut`
to manually perform this cast since it is safe in our case and because
this fix will eventually land on main (currently present on nightly
1.97).

See rust-lang/rust#153438 and
rust-lang/rust#153457.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates several select_slice call sites that build a heapless::Vec of futures, replacing an implicit pin/coercion pattern with an explicit Pin::map_unchecked_mut cast to a pinned slice to avoid relying on known-unsound coercion behavior in pin! (per rust-lang issue #153438).

Changes:

  • Replace select_slice(pin!(...)) usage with pin!(futures) + unsafe { pinned.map_unchecked_mut(|f| f.as_mut()) } to obtain a pinned slice explicitly.
  • Add inline comments documenting the pinning and safety rationale near the unsafe conversion.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
type-c-service/src/service/event_receiver.rs Updates port event receiver selection to use an explicit pinned-slice conversion for select_slice.
power-policy-service/src/psu.rs Updates PSU event selection to use an explicit pinned-slice conversion for select_slice.
power-policy-service/src/charger.rs Updates charger event selection to use an explicit pinned-slice conversion for select_slice.

Comment thread type-c-service/src/service/event_receiver.rs
Comment thread type-c-service/src/service/event_receiver.rs
Comment thread power-policy-service/src/psu.rs
Comment thread power-policy-service/src/psu.rs
Comment thread power-policy-service/src/charger.rs
Comment thread power-policy-service/src/charger.rs
@RobertZ2011 RobertZ2011 marked this pull request as ready for review June 18, 2026 18:51
@RobertZ2011 RobertZ2011 requested review from a team as code owners June 18, 2026 18:51
@theemathas

Copy link
Copy Markdown

I'm not sure whether this is sound or not. See list item 3 (Structural Notice of Destruction) at https://doc.rust-lang.org/nightly/std/pin/index.html#choosing-pinning-to-be-structural-for-field.

@RobertZ2011

Copy link
Copy Markdown
Contributor Author

I'm not sure whether this is sound or not. See list item 3 (Structural Notice of Destruction) at https://doc.rust-lang.org/nightly/std/pin/index.html#choosing-pinning-to-be-structural-for-field.

@theemathas Thanks for taking a look, I appreciate it. My understanding is that there shouldn't be any invalidation issues with heapless::Vec because the storage is a stack allocated array and no resizing or similar modifications are done to that storage after pinning. The Drop implementation for heapless::Vec uses drop_in_place so it should be good as well. I do see the mention of VecDeque<T> and how that would apply here. Is the concern that the compiler-generated future could have a Drop implementation that panics and the unsoundness could come in there?

@theemathas

Copy link
Copy Markdown

Ah right, heapless is using a single drop_in_place call for the whole vec, so I think it's fine. Sorry for the noise.

@theemathas

Copy link
Copy Markdown

The important part is that if one future's drop panics, the other futures still must be dropped. I think drop_in_place on a slice does that.

@RobertZ2011

Copy link
Copy Markdown
Contributor Author

Ah right, heapless is using a single drop_in_place call for the whole vec, so I think it's fine. Sorry for the noise.

No worries, this is definitely a part of Rust that I don't engage with very often so I'm happy to have another set of eyes on it.

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.

5 participants