unwrap_or_default: respect MSRV for raw-pointer Default impls - #17452
unwrap_or_default: respect MSRV for raw-pointer Default impls#17452uditjainstjis wants to merge 1 commit into
Conversation
|
Thanks for the pull request, and welcome! You should hear from one of our reviewers after this PR gets at least 2 reviews from the community. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
This comment has been minimized.
This comment has been minimized.
59e743a to
3532097
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
There was a problem hiding this comment.
Community review: makes sense to me
But, since you couldn't add a test for this (with a reasonable explanation for why) can you please
- document with an inline comment the situations in which this is actually triggerable (since people might see that removing that code doesn't break any tests)
- test locally and confirm that this no longer fires for the std build?
3532097 to
2d360f5
Compare
|
Both done. 1. Inline comment. Amended into the commit, so the "changes since review" link won't help — here it is verbatim: // The `Default` implementations for raw pointers (`*const T`, `*mut T`) were only stabilized in
// 1.88.0. Suggesting `unwrap_or_default()` below that MSRV would produce code that does not
// compile, so bail out in that case (see #17379).
//
// This is not covered by a UI test, so to be clear about when it is reachable: the value has to
// be recognized as a default one by `is_default_equivalent`, which for `ptr::null()` compares
// MIR against `<*const T as Default>::default()`. In practice that only happens under
// `-Zbuild-std`; against the precompiled `std` the UI tests run on, the lint never reaches here
// for raw pointers, which is why this cannot be covered by a test. So removing this check
// breaks no test, but it does reintroduce the false positive on
// `opt.unwrap_or(core::ptr::null())` for build-std users such as the Linux kernel.2. Tested locally. I read "the std build" as building Test crate: #![feature(custom_inner_attributes)]
#![warn(clippy::unwrap_or_default)]
#![clippy::msrv = "1.85"]
pub fn f(o: Option<*const u8>) -> *const u8 { o.unwrap_or(core::ptr::null()) }
pub fn g(o: Option<*mut u8>) -> *mut u8 { o.unwrap_or(core::ptr::null_mut()) }
pub fn h(o: Option<*const u8>) -> *const u8 { o.unwrap_or_else(core::ptr::null) }run against a locally built clippy with
So it suppresses exactly the below-MSRV case and nothing more. Two things that came out of it:
|
There was a problem hiding this comment.
Both done.
1. Inline comment. Amended into the commit, so the "changes since review" link won't help — here it is verbatim:
The triagebot link does show the changed comment, https://triagebot.infra.rust-lang.org/gh-range-diff/rust-lang/rust-clippy/a63d11b92b45931a5e789c56e01e772e17c278fa..3532097ae2ab397c13d142927b9727f0e1ee80bf/84544006d21b57688f3e92af1683df923868cd51..2d360f53d61124b3bd61341e392b7657b3438a95
2. Tested locally. I read "the std build" as building
stdfrom source, since that is the configuration the kernel report hits — say the word if you meant running clippy over the library itself instead and I'll do that.
I just wanted to confirm that this was tested to fix the bug that led to the report being filed, and you seem to have indeed tested this fully
|
r? @dswij rustbot has assigned @dswij for the project review. Use Why was this reviewer chosen?The reviewer was selected based on:
|
| // The `Default` implementations for raw pointers (`*const T`, `*mut T`) were only stabilized in | ||
| // 1.88.0. Suggesting `unwrap_or_default()` below that MSRV would produce code that does not | ||
| // compile, so bail out in that case (see #17379). | ||
| // | ||
| // This is not covered by a UI test, so to be clear about when it is reachable: the value has to | ||
| // be recognized as a default one by `is_default_equivalent`, which for `ptr::null()` compares | ||
| // MIR against `<*const T as Default>::default()`. In practice that only happens under | ||
| // `-Zbuild-std`; against the precompiled `std` the UI tests run on, the lint never reaches here | ||
| // for raw pointers, which is why this cannot be covered by a test. So removing this check | ||
| // breaks no test, but it does reintroduce the false positive on | ||
| // `opt.unwrap_or(core::ptr::null())` for build-std users such as the Linux kernel. |
There was a problem hiding this comment.
nit: seems overburdening. a shorter one likely also suffices.
Also might need an format, I don't know the line length by heart
| // The `Default` implementations for raw pointers (`*const T`, `*mut T`) were only stabilized in | |
| // 1.88.0. Suggesting `unwrap_or_default()` below that MSRV would produce code that does not | |
| // compile, so bail out in that case (see #17379). | |
| // | |
| // This is not covered by a UI test, so to be clear about when it is reachable: the value has to | |
| // be recognized as a default one by `is_default_equivalent`, which for `ptr::null()` compares | |
| // MIR against `<*const T as Default>::default()`. In practice that only happens under | |
| // `-Zbuild-std`; against the precompiled `std` the UI tests run on, the lint never reaches here | |
| // for raw pointers, which is why this cannot be covered by a test. So removing this check | |
| // breaks no test, but it does reintroduce the false positive on | |
| // `opt.unwrap_or(core::ptr::null())` for build-std users such as the Linux kernel. | |
| // Without stable `Default` for raw pointers (1.88.0), this is a compilation error | |
| // In practice that only happens under `-Zbuild-std`, so not covereded by our ui tests under precompiled `std`. |
The `Default` impls for `*const T` / `*mut T` were only stabilized in 1.88.0, so `or_fun_call` must not suggest `unwrap_or_default()` for a raw-pointer value below that MSRV; the resulting code would fail to compile.
2d360f5 to
e0a5c4a
Compare
|
Fair 😄 — cut it down to four lines, keeping only the bit that stops someone deleting the check because no test covers it: // `Default` for raw pointers is only stable since 1.88.0, so the suggestion would not compile
// below that MSRV (#17379). Only reachable under `-Zbuild-std`, hence not covered by our UI
// tests against a precompiled `std` — removing this breaks no test, but does bring the false
// positive back for build-std users.
|
or_fun_call(through itsunwrap_or_defaultsuggestion) rewritesopt.unwrap_or(core::ptr::null())toopt.unwrap_or_default(). TheDefaultimpls for*const T/*mut Twere only stabilized in 1.88.0, so under a lower MSRV the suggested code does not compile. This was hit in the Linux kernel (msrv = "1.85", built with-Copt-level=s) — see the report linked from #17379.This adds a
RAW_PTR_DEFAULT(1.88.0) MSRV alias and bails out of theunwrap_or_defaultsuggestion when the default value is a raw pointer and the MSRV is not met.A note on testing
I could not reproduce the false positive in the UI test harness. The lint only recognises
core::ptr::null()as a default value throughis_default_equivalent's MIR comparison against<*const T as Default>::default(), which needs that impl's MIR to be available. That happens with-Zbuild-std(as in the kernel build), but with the precompiledstdthe harness uses,is_mir_availableisfalse, so the lint never fires for raw pointers and a#[clippy::msrv]regression test can't trigger it. The reproduction is therefore the linked kernel report. Happy to add a test if there's a preferred way to exercise the build-std path, or to gate this differently.fixes #17379
changelog: [
unwrap_or_default]: don't suggestunwrap_or_default()for a raw-pointer value below the 1.88 MSRV that stabilizedDefaultfor raw pointers