Skip to content

RUST-2412 Provide an operation wrapper abstraction#1738

Open
abr-egn wants to merge 4 commits into
mongodb:mainfrom
abr-egn:RUST-2412/operation-wrapper
Open

RUST-2412 Provide an operation wrapper abstraction#1738
abr-egn wants to merge 4 commits into
mongodb:mainfrom
abr-egn:RUST-2412/operation-wrapper

Conversation

@abr-egn

@abr-egn abr-egn commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

RUST-2412

Not directly related to the main work for this ticket, but that involves adding a field to Operation and I got annoyed at having to always update the various wrappers.

This adds an OperationWrapper trait that knows how to dispatch to a generic inner Operation; this means that the various places we have such (four as of this writing) are both easier to read, since they only need to list out the methods where the behavior is changed by the wrapper, and don't have to be updated when we add new methods to the core trait.

The downside is that, because we can't have two blanket traits that impl Operation for OperationWithDefaults and OperationWrapper, those now work via a helper trait OperationDispatch and tag trait OperationImpl. IMO, this is worth it because the added boilerplate per-operation is minimal and the helpers are largely ignorable (nothing outside the one blanket impl in operation.rs needs to care about OperationDispatch).

Comment thread driver/src/operation.rs
}

impl<T: OperationWithDefaults> Operation for T
pub(crate) trait OperationDispatch<Kind> {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This intermediate trait is needed because the rule is that there can be only one blanket impl per trait, so the blanket impl is Operation for OperationDispatch<K>. The blanket impls for the helper traits don't run into this issue because OperationDispatch<WithDefaults> and OperationDispatch<Wrapper> are considered to be distinct traits for the purposes of overlap checks.

Ideally we could just include OperationImpl<Kind=WithDefaults> / <Kind=Wrapper> in a blanket Operation impl but it turns out there's a longstanding compiler bug that prevents that 🙁

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.

Makes sense - can you add a comment on this file explaining the basic trait hierarchy? I don't think I'll remember this rationale next time I look at this 🙂

@abr-egn

abr-egn commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

The failures here are fixed by #1739.

@abr-egn abr-egn marked this pull request as ready for review July 13, 2026 15:24
@abr-egn abr-egn requested a review from a team as a code owner July 13, 2026 15:24
@abr-egn abr-egn requested a review from isabelatkinson July 13, 2026 15:24
@abr-egn abr-egn force-pushed the RUST-2412/operation-wrapper branch from 2873c7e to 3e6c9fd Compare July 13, 2026 16:03
}

impl OperationImpl for Create {
type Kind = WithDefaults;

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.

I think the WithDefaults naming is more descriptive of the implementation than the concept. Can we change this to be something like Base or Root? And ditto for the OperationWithDefaults trait - something like BaseOperation or RootOperation would make it more clear that the types that define that trait are ones that don't wrap another operation.

(Not necessarily a new concern on this PR, but something I got to thinking about more while reviewing.)

Comment thread driver/src/operation.rs
}

impl<T: OperationWithDefaults> Operation for T
pub(crate) trait OperationDispatch<Kind> {

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.

Makes sense - can you add a comment on this file explaining the basic trait hierarchy? I don't think I'll remember this rationale next time I look at this 🙂

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.

2 participants