-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
refining_impl_trait: Decide whether explicit opt-in is needed #121718
Comments
…-errors Split refining_impl_trait lint into _reachable, _internal variants As discussed in rust-lang#119535 (comment): > We discussed this today in triage and developed a consensus to: > > * Add a separate lint against impls that refine a return type defined with RPITIT even when the trait is not crate public. > * Place that in a lint group along with the analogous crate public lint. > * Create an issue to solicit feedback on these lints (or perhaps two separate ones). > * Have the warnings displayed with each lint reference this issue in a similar manner to how we do that today with the required `Self: '0'` bound on GATs. > * Make a note to review this feedback on 2-3 release cycles. This points users to rust-lang#121718 to leave feedback.
Rollup merge of rust-lang#121720 - tmandry:split-refining, r=compiler-errors Split refining_impl_trait lint into _reachable, _internal variants As discussed in rust-lang#119535 (comment): > We discussed this today in triage and developed a consensus to: > > * Add a separate lint against impls that refine a return type defined with RPITIT even when the trait is not crate public. > * Place that in a lint group along with the analogous crate public lint. > * Create an issue to solicit feedback on these lints (or perhaps two separate ones). > * Have the warnings displayed with each lint reference this issue in a similar manner to how we do that today with the required `Self: '0'` bound on GATs. > * Make a note to review this feedback on 2-3 release cycles. This points users to rust-lang#121718 to leave feedback.
User feedback: |
Personally I like ... is it refinement when the |
I don't really care; I'd prefer not needing to opt-in, but I'm fine either way. |
Prefered in this way with |
#[allow(refining_impl_trait)] is ok for me |
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
Summary: Release notes: https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html Stabilized features: - `absolute_path` - `associated_type_bounds` - `inline_const` - `pointer_is_aligned` - `slice_ptr_len` This release raises a new warning when a trait impl contains a signature that is more refined than the corresponding signature in the trait, impacting `buck2_query`. ```lang=text warning: impl trait in impl method signature does not match trait method signature --> fbcode/buck2/app/buck2_query/src/query/environment/tests.rs:73:30 | 73 | fn deps<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::Key> + Send + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ::: fbcode/buck2/app/buck2_query/src/query/environment.rs:98:30 | 98 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a Self::Key> + Send + 'a; | ----------------------------------------------- return type from trait method defined here | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 <rust-lang/rust#121718> for more information = note: `#[warn(refining_impl_trait_internal)]` on by default help: replace the return type so that it matches the trait | 73 | fn deps<'a>(&'a self) -> impl Iterator<Item = &'a <Self as node::LabeledNode>::Key> + std::marker::Send + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` It also contains changes to the `dead_code` lint, which are addressed in {D59622902} and {D59623034}. Reviewed By: zertosh Differential Revision: D58982552 fbshipit-source-id: a17eaf91d07234209fddf5cbdebce4424dda57ae
(not sure if this is the right thread for this) I just hit a funky case that caused this lint where I didn't expect it, in code like this: trait DoSomething {
fn do_something() -> impl Future;
}
struct SomethingDoer;
impl DoSomething for SomethingDoer {
async fn do_something() {}
} If I specify the output type of Generally, I'm fine with whatever |
Ran into this dealing with Because the This can be worked around by making an explicit internal copy of the function, but this doesn't seem great. |
You can also get around it by annotating the impl P for str {
fn try_iter(&self) -> Option<impl Iterator<Item = u32>> {
None::<std::array::IntoIter<u32, 0>>
}
} Still not perfect that you have to annotate the |
Generic bounds applied to trait methods also have some unexpected quirky behavior under refinement — I opened #129251 to avoid cluttering this issue with a tangent. |
I think it should warn for both public and internal impls; leaking internal implementation details to oneself should also be a conscious decision. It would be nice if it would become a hard error, but it is probably not worth it. In any case, |
For me refinements are useful, and I expect that crates that use my library could avoid unnecessary conversions. pub trait Whatever {
fn id(&self) -> impl ToString;
}
pub struct InternalObjectString<'a> {
id: &'a str,
}
impl<'a> Whatever for InternalObjectString<'a> {
fn id(&self) -> String {
self.id.to_string()
}
}
pub struct InternalObjectInt {
id: u32
}
impl<'a> Whatever for InternalObjectInt {
fn id(&self) -> u64 {
self.id as u64
}
}
// In other crate
use whatever::Whatever;
struct ExternalCrateObject {
id: u32,
}
impl Whatever for ExternalCrateObject {
fn id(&self) -> u32 {
self.id
}
} In my case, types that implement I also prefer that the type that implements the trait could be stricter and more explicit about the types of its methods. So:
About introducing I'd introduce it only if it is necessary for the internal API too, or if it can be used in more contexts. Some ideas:
pub trait Whatever {
#[refine(String)]
fn id(&self) -> impl ToString;
}
trait Number {
#[refine(return < 0)]
const fn negative(&self) -> impl Into<i32> {
-1
}
} |
What is
refining_impl_trait
?The
refining_impl_trait
lints detect usages of return-position impl traits in trait signatures which are refined by implementations, meaning the implementation adds information about the return type that is not present in the trait.Example
The above code compiles, but produces a warning:
Explanation
Callers of methods for types where the implementation is known are able to observe the types written in the impl signature. This may be intended behavior, but may also lead to implementation details being revealed unintentionally. In particular, it may pose a semver hazard for authors of libraries who do not wish to make stronger guarantees about the types than what is written in the trait signature.
Future possibilities
Add an explicit
#[refine]
attribute. This would make it easier to opt in to refining on a per-method basis and make the refine check feel more like a builtin feature of the language.Make
refining_impl_trait
error-by-default in a future edition. This would mean we are committed to explicit refinement for impl Traits. Since this would happen over an edition, we could choose to go even further and make it a hard error so you could not blanket-allow it in your crate.Keep all
refining_impl_trait
warn-by-default.Make
refining_impl_trait_internal
allow-by-default, but keeprefining_impl_trait_reachable
warn-by-default. This would mean that we think semver hazards for publicly-reachable traits in a crate are important enough to lint against. But for uses internal to a crate, opting in is unnecessary overhead for the user.Make all
refining_impl_trait
allow-by-default. This would mean that we think most uses of refinement for return-position impl Trait are deliberate and unlikely to cause semver hazards or other unexpected behavior.Discussion
The language team is collecting feedback about this lint. We would like to know
#[refine]
attribute in the future.The text was updated successfully, but these errors were encountered: