-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Warn if an item coming from more recent version than MSRV is used #12160
Conversation
r? @dswij (rustbot has picked a reviewer for you, use r? to override) |
c3038d0
to
d95ce5d
Compare
63cd7d0
to
2954332
Compare
r? @blyxyas |
I'm not sure if this should be on Although I'm not sure why Clippy has a MSRV concept though, as if a project has a MSRV CI would already build it with that Rust version... But those are philosophical questions we don't do (・∀・) |
For myself, I see this being useful for catching problems in development (since enough people run clippy locally, whether directly or via editor plugins) rather than waiting until a PR is posted and waiting for the CI run to fail. |
Same as @epage for me. I can think of one extra case: people not ensuring that in CI (bad practice but I think it's definitely not uncommon) and who discover the MSRV breakage when they try to publish. |
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.
Very good first iteration! Meow meow, just a few nits and questions, but I'll approve this one already (it could be merged in this state, but I just want to clarify a few things)
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// It would prevent this project to be actually used with the specified MSRV. |
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.
/// It would prevent this project to be actually used with the specified MSRV. | |
/// It would prevent the crate to be actually used with the specified MSRV. |
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.
Done. 👍
} => Some(RustcVersion::new( | ||
version.major as _, | ||
version.minor as _, | ||
version.patch as _, | ||
)), |
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.
Meow (does this work?)
} => Some(RustcVersion::new( | |
version.major as _, | |
version.minor as _, | |
version.patch as _, | |
)), | |
} => Some(version), |
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.
Doesn't work unfortunately:
error[E0308]: `if` and `else` have incompatible types
--> clippy_lints/src/incompatible_msrv.rs:72:16
|
62 | let version = if let Some(version) = tcx
| ________________________-
63 | | .lookup_stability(def_id)
64 | | .and_then(|stability| match stability.level {
65 | | StabilityLevel::Stable {
... |
71 | | version
| | ------- expected because of this
72 | | } else if let Some(parent_def_id) = tcx.opt_parent(def_id) {
| | ________________^
73 | || self.get_def_id_version(tcx, parent_def_id)
74 | || } else {
75 | || RustcVersion::new(1, 0, 0)
76 | || };
| || ^
| ||_________|
| |_________`if` and `else` have incompatible types
| expected `RustcVersion`, found `rustc_semver::RustcVersion`
|
= note: `rustc_semver::RustcVersion` and `RustcVersion` have similar names, but are actually distinct types
note: `rustc_semver::RustcVersion` is defined in crate `rustc_semver`
--> /home/imperio/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustc-semver-1.1.0/src/lib.rs:58:1
|
58 | pub enum RustcVersion {
| ^^^^^^^^^^^^^^^^^^^^^
note: `RustcVersion` is defined in crate `rustc_session`
|
||
#[allow(clippy::cast_lossless)] | ||
fn get_def_id_version(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> RustcVersion { | ||
if let Some(version) = self.is_above_msrv.get(&def_id) { |
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 for this light caching, it does indeed work! yeehaw 🤠
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.
😃
fn enter_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { | ||
self.msrv.enter_lint_attrs(cx.tcx.sess, attrs); | ||
} | ||
|
||
fn exit_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { | ||
self.msrv.exit_lint_attrs(cx.tcx.sess, attrs); | ||
} |
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 can use extract_msrv_attr!
, if you want :3 although this approach doesn't disgust me.
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.
Knowing about this would have saved me so much XD
/// available in your current MSRV. | ||
#[clippy::version = "1.77.0"] | ||
pub INCOMPATIBLE_MSRV, | ||
suspicious, |
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.
So... What do you think about putting this lint in correctness
?
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 think it's pretty low risk (ie, warning will very likely always be right) to keep it into suspicious
. Happened to me a few times and I would have loved to know earlier on that I was doing something wrong.
2093bf1
to
fb77402
Compare
Applied suggestions (thanks!) and replied to questions. |
let version = if let Some(version) = tcx | ||
.lookup_stability(def_id) | ||
.and_then(|stability| match stability.level { | ||
StabilityLevel::Stable { | ||
since: StableSince::Version(version), | ||
.. | ||
} => Some(RustcVersion::new( |
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.
In case stable
gets stabilized, should we guard this to be exclusive to certain crates? Or should we wait until that wished for day to arrive?
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.
(and yes, when its stabilized, I would love to tell clippy or rustc the minimum version for every dependency and have a lint to catch crate dependencies and not just std/alloc/core)
INCOMPATIBLE_MSRV, | ||
span, | ||
&format!( | ||
"current MSRV is `{}` but this item is stable since `{version}`", |
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.
Should we spell out MSRV for those less familiar?
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.
Let's do that. 👍
/// To fix this problem, either increase your MSRV or use another item | ||
/// available in your current MSRV. | ||
#[clippy::version = "1.77.0"] | ||
pub INCOMPATIBLE_MSRV, |
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'm a bit hesitant about using "msrv" because (1) it is an acronym and (2) not everyone knows what it means.
Would "incompatible_rust_version` work for a lint name?
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.
Hum... What do you think about incompatible_minimum_rust_version
?
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.
No meaningful preference either way.
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'll go for the more explicit one then.
Renamed and update the error message to clear up confusion. |
I'm not sure about the new changes.
Hmmm, the case where spelling it would be useful would be if: An author that has not been communicated of the existence of the MSRV in that codebase (No contributing guide / mentorship), is using a function stabilized later than the MSRV, hasn't seen the If you want to cover that edge case, we can presume that the same person that wrote |
True, I said |
830b891
to
69c6fa3
Compare
I removed the last commit (which renamed the lint). I also agree with @epage but whatever clippy maintainers prefer. :) |
I agree that acronyms can impede communications, but in this case where we have a So the only time where an user would use an attribute would be to either deny the lint or allow it. Both scenarios happen where the user already knows of the lint's existence (and thus, the lint message already explained). Also, the user can use |
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.
A mini-nit on the test and this is merge-ready!
tests/ui/incompatible_msrv.rs
Outdated
// Stable since 1.10, so should not warn. | ||
assert_eq!(map.entry("poneyland").key(), &"poneyland"); |
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.
// Stable since 1.10, so should not warn. | |
assert_eq!(map.entry("poneyland").key(), &"poneyland"); | |
assert_eq!(map.entry("poneyland").key(), &"poneyland"); | |
//~^ ERROR: is `1.3.0` but this item is stable since `1.10.0` |
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.
Done!
69c6fa3
to
f7b9d03
Compare
=^w^= great! Could you squash these commits? |
Done as well. |
f7b9d03
to
14e1520
Compare
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.
LGTM, thanks! ❤️
@bors r+ |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
Part of #6324.
Currently, the lint is not working for the simple reason that thestable
attribute is not kept in dependencies. I'll send a PR to rustc to see if they'd be okay with keeping it.EDIT: There was actually a
lookup_stability
function providing this information, so all good now!cc @epage
changelog: create new [
incompatible_msrv
] lint