Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

seals PyAnyMethods and friends #3909

Merged
merged 2 commits into from
Feb 28, 2024
Merged

seals PyAnyMethods and friends #3909

merged 2 commits into from
Feb 28, 2024

Conversation

Icxolu
Copy link
Contributor

@Icxolu Icxolu commented Feb 27, 2024

Part of #3684, following #3684 (comment)

This seals these new traits, preventing downstream crates from implementing them on their types. These traits are mainly a workaround for arbitrary self receiver types, so this gives us more flexibility if these need to be changed in the future.

This seals these new traits, preventing downstream
crates from implementing them on their types.
These traits are mainly a workaround for arbitrary
self receiver types, so this gives us more
flexibility if these need to be changed in the
future.
@Icxolu Icxolu added the CI-skip-changelog Skip checking changelog entry label Feb 27, 2024
Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this!

I have one further question regarding possible additional cleanup...

};
use crate::{ffi, Bound, PyAny};

pub trait Sealed {}
Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to have a single Sealed trait for the whole crate, or should we have multiple Sealed traits each only relevant for one or more types?

We have Sealed for PyResultExt trait too, which could be merged in I guess, if it makes sense to do so.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't think of an advantage of using multiple Sealed traits. The only relevant property is that it is a public trait, but not publicly nameable. If you can think of a good reason to split, I'm happy to do so, otherwise a central location is easy for reuse and might be easier to track changes in the future.

Hmm, now that I wrote that, maybe one disadvantage is that the sealed module is not completely private anymore, so implementation of the Sealed trait could be added anywhere in the crate instead of only in that module... How do you feel about that?

Copy link
Member

@davidhewitt davidhewitt Feb 27, 2024

Choose a reason for hiding this comment

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

I think I'm not worried about us implementing from anywhere in the crate, we can prevent that in review.

I think what I was wondering is, e.g. imagine we have a trait Foo which we only ever want implemented for Bound<T>. We seal it and we implement sealed for Bound<T>.

By adding that sealing for generic T now users can implement PyDictMethods for their own Bound<MyClass>.

If the sealing was done by separate traits then we could guarantee that the PyDictMethods seal would only ever allow Bound<PyDict> and not accidentally gave this mistake.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe I am putting the cart before the horse, and for now we should just live with one Sealed trait because orphan rules will stop users adding further implementations to any of the types we've sealed here.

If there's a need to seal for a generic, we can think carefully about that at the time 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, sealing a generic type will require more (careful) thoughts. I agree that we can think about that, once we have a use case for it.

@@ -55,7 +55,7 @@ impl PyBool {
/// syntax these methods are separated into a trait, because stable Rust does not yet support
/// `arbitrary_self_types`.
#[doc(alias = "PyBool")]
pub trait PyBoolMethods<'py> {
pub trait PyBoolMethods<'py>: crate::sealed::Sealed {
Copy link
Member

@davidhewitt davidhewitt Feb 27, 2024

Choose a reason for hiding this comment

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

Does rustdoc render the bound as Sealed or crate::sealed::Sealed? That might affect whether we use the trait first or go for the full path like here (if you think it matters).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

image
It seems it does not make a difference, this looks fine to me.

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Having thought about this further, I think this looks good to me! Thanks 👍

};
use crate::{ffi, Bound, PyAny};

pub trait Sealed {}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe I am putting the cart before the horse, and for now we should just live with one Sealed trait because orphan rules will stop users adding further implementations to any of the types we've sealed here.

If there's a need to seal for a generic, we can think carefully about that at the time 👍

@davidhewitt davidhewitt added this pull request to the merge queue Feb 28, 2024
Merged via the queue into PyO3:main with commit 5583336 Feb 28, 2024
42 checks passed
@Icxolu Icxolu deleted the seal-traits branch February 28, 2024 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI-skip-changelog Skip checking changelog entry
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants