-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Suggest Option<&T>
instead of &Option<T>
#13336
Conversation
798a03f
to
55404f9
Compare
I'd shorten the name to |
@llogiq I would rather finish at least the first two TODOs before merging, but I can already use your help because there are a lot of in-code TODOs that I could use some help with. Thx! |
6b40c38
to
16a588a
Compare
@llogiq I think I'm done with the changes I wanted to make - now it is all open questions and review :) |
This could break code that mutates the |
@PatchMixolydic could you give a full example to make sure we evaluate it properly? I am suspecting |
Example:
|
@llogiq thx, but we should discuss it as a full "semi-working" example - i.e. as a function param. Although if you are also certain this should not be checked, i will just exclude it from the lint |
Yes, I am certain this should not be linted. Please exclude it by only linting immutable RPtrs. |
Should both of these cases be ignored? fn mut_1(a: &mut Option<String>) {}
fn mut_2(a: &mut &Option<String>) {} |
No, only the direct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some feedback re your TODOs. Hopefully this should give you a clear path forward.
clippy_lints/src/functions/mod.rs
Outdated
/// Warns when a function signature uses `&Option<T>` instead of `Option<&T>`. | ||
/// ### Why is this bad? | ||
/// More flexibility, better memory optimization, and more idiomatic Rust code. | ||
/// See [YouTube video](https://www.youtube.com/watch?v=6c7pZYP_iIE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// See [YouTube video](https://www.youtube.com/watch?v=6c7pZYP_iIE) | |
/// See this [YouTube video](https://www.youtube.com/watch?v=6c7pZYP_iIE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the video title and author/channel would also be nice, as it would serve as alt
text
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Rudxain how can you add an alt text to a non-image/video link? I thought the ![Alt text](...)
is only for images and such. Please give an example of what you think this markdown should be like. I couldn't find any other code in the rust repo that had alt text like this. Thx!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, you could try to summarize succintly the key reasoning from the YouTube video for why this might enable better optimizations (i.e. it's unlikely people are going to want to watch a youtube video linked from doc comments).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should also copy-pasta your summary to your PR description, makes it easier to understand why your PR included these changes 😸
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add an alt text to a non-image/video link?
I'm sorry for not being clear. I meant it as "equivalent to alt
" not literally an alt
. It doesn't matter how you add the extra information, what matters is the information itself.
I was thinking of a good ol' link: the "name" of the link can be used as an alt
:
[This link points to an example web page](https://example.org)
b0f0e62
to
87e6df6
Compare
2eb85d2
to
7abb99a
Compare
Migrate compiler's `&Option<T>` into `Option<&T>` Similar to rust-lang#130962 but for the compiler. Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations.
7abb99a
to
73a16c1
Compare
clippy_lints/src/functions/mod.rs
Outdated
/// `&Option<T>` in a function signature breaks encapsulation because the caller must own T | ||
/// and move it into an Option to call with it. When returned, the owner must internally store | ||
/// it as `Option<T>` in order to return it. | ||
/// At a lower level `&Option<T>` points to memory that has `presence` bit flag + value, | ||
/// whereas `Option<&T>` is always optimized to a single pointer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remark: it would be good if we can reference any guarantees that these optimizations are performed for justification of this lint. We should double-check Option<T>
representation guarantees by std docs: https://doc.rust-lang.org/std/option/index.html#representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx, i updated the text with the link
clippy_lints/src/functions/mod.rs
Outdated
/// At a lower level `&Option<T>` points to memory that has `presence` bit flag + value, | ||
/// whereas `Option<&T>` is always optimized to a single pointer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: is this always guaranteed, or is it only guaranteed if T: Sized
(I haven't looked very hard myself)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I haven't looked into this too far; please take everything I say with a grain of salt)
Option
's documentation in std
only guarantees this for &{,mut} impl Sized
, but it seems like the Unsafe Code Guidelines Working Group tenatively posit that similar optimizations occur for all values with a niche, which would include &{,mut} impl !Sized
(as all references must be nonnull, even if their pointee is !Sized
).
Obviously, though, Option<&impl
!Thin
>
cannot be optimized to a thin pointer, and there does not seem to be any guarantee about what the metadata component would be in None::<&impl !Thin>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, which is why I asked, because I wasn't sure if this is always the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The real question is if we want to have all this complexity explained in a lint? I agree we should link to the options doc, and perhaps talk about possible performance improvement. Any suggestions on the wording?
An even more important question is: how common is a case where API is deliberately, as oppose to accidentally, designed to take or return &Option<T>
? If this is extremely rare, I think it makes sense to promote this to style
, at least in the longer term.
As part of this, also modify `Option<&String>` to `Option<&str>`, same for `PathBuf` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
As part of this, also modify `Option<&String>` to `Option<&str>`, same for `PathBuf` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
Looks ok to me. Thank you! @bors r+ |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
As part of this, also modify `Option<&String>` to `Option<&str>`, same for `PathBuf` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
As part of this, also modify `Option<&String>` to `Option<&str>`, same for `PathBuf` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
Convert `&Option<T>` to `Option<&T>` Run `ref_option` (#13336) on the Clippy's own code, quiet a few hits. Per mentioned video, this may actually improve performance as well. Switch lint to `pedantic` changelog [`ref_option`]: upgrade lint to `pedantic`
Convert `&Option<T>` to `Option<&T>` Run `ref_option` (#13336) on the Clippy's own code, quiet a few hits. Per mentioned video, this may actually improve performance as well. Switch lint to `pedantic` ---- changelog: [`ref_option`]: upgrade lint to `pedantic`
Migrate lib's `&Option<T>` into `Option<&T>` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
Rollup merge of rust-lang#130962 - nyurik:opts-libs, r=cuviper Migrate lib's `&Option<T>` into `Option<&T>` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
Migrate lib's `&Option<T>` into `Option<&T>` Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations. Basic thoughts expressed in the video that seem to make sense: * `&Option<T>` in an API breaks encapsulation: * caller must own T and move it into an Option to call with it * if returned, the owner must store it as Option<T> internally in order to return it * Performance is subject to compiler optimization, but at the basics, `&Option<T>` points to memory that has `presence` flag + value, whereas `Option<&T>` by specification is always optimized to a single pointer.
closes #13054
Handles argument types and return types in functions, methods, and closures with explicit types. Honors
avoid_breaking_exported_api
parameter.See this great YouTube video with the in-depth explanation.
Open Questions
These are not blocking, and could be done in separate PRs if needed.
&Option<Box<T>>
be suggested asOption<&T>
-- without the box? Handled by clippy::borrowed_box&Option<String>
be suggested asOption<&str>
-- using de-refed type?Possible Future Improvements
These cases might also be good to handle, probably in a separate PR.
changelog: [
ref_option
]: SuggestOption<&T>
instead of&Option<T>