@@ -2,7 +2,7 @@ use clippy_config::Conf;
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
3
use clippy_utils:: is_in_test;
4
4
use clippy_utils:: msrvs:: Msrv ;
5
- use rustc_attr_parsing:: { RustcVersion , StabilityLevel , StableSince } ;
5
+ use rustc_attr_parsing:: { RustcVersion , Stability , StableSince } ;
6
6
use rustc_data_structures:: fx:: FxHashMap ;
7
7
use rustc_hir:: { Expr , ExprKind , HirId , QPath } ;
8
8
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -72,9 +72,15 @@ declare_clippy_lint! {
72
72
"ensures that all items used in the crate are available for the current MSRV"
73
73
}
74
74
75
+ #[ derive( Clone , Copy ) ]
76
+ enum Availability {
77
+ FeatureEnabled ,
78
+ Since ( RustcVersion ) ,
79
+ }
80
+
75
81
pub struct IncompatibleMsrv {
76
82
msrv : Msrv ,
77
- is_above_msrv : FxHashMap < DefId , RustcVersion > ,
83
+ availability_cache : FxHashMap < DefId , Availability > ,
78
84
check_in_tests : bool ,
79
85
}
80
86
@@ -84,35 +90,32 @@ impl IncompatibleMsrv {
84
90
pub fn new ( conf : & ' static Conf ) -> Self {
85
91
Self {
86
92
msrv : conf. msrv ,
87
- is_above_msrv : FxHashMap :: default ( ) ,
93
+ availability_cache : FxHashMap :: default ( ) ,
88
94
check_in_tests : conf. check_incompatible_msrv_in_tests ,
89
95
}
90
96
}
91
97
92
- fn get_def_id_version ( & mut self , tcx : TyCtxt < ' _ > , def_id : DefId ) -> RustcVersion {
93
- if let Some ( version) = self . is_above_msrv . get ( & def_id) {
94
- return * version;
98
+ /// Returns the availability of `def_id`, whether it is enabled through a feature or
99
+ /// available since a given version (the default being Rust 1.0.0).
100
+ fn get_def_id_availability ( & mut self , tcx : TyCtxt < ' _ > , def_id : DefId ) -> Availability {
101
+ if let Some ( availability) = self . availability_cache . get ( & def_id) {
102
+ return * availability;
95
103
}
96
- let version = if let Some ( version) = tcx
97
- . lookup_stability ( def_id)
98
- . and_then ( |stability| match stability. level {
99
- StabilityLevel :: Stable {
100
- since : StableSince :: Version ( version) ,
101
- ..
102
- } => Some ( version) ,
103
- _ => None ,
104
- } ) {
105
- version
104
+ let stability = tcx. lookup_stability ( def_id) ;
105
+ let version = if stability. is_some_and ( |stability| tcx. features ( ) . enabled ( stability. feature ) ) {
106
+ Availability :: FeatureEnabled
107
+ } else if let Some ( StableSince :: Version ( version) ) = stability. as_ref ( ) . and_then ( Stability :: stable_since) {
108
+ Availability :: Since ( version)
106
109
} else if let Some ( parent_def_id) = tcx. opt_parent ( def_id) {
107
- self . get_def_id_version ( tcx, parent_def_id)
110
+ self . get_def_id_availability ( tcx, parent_def_id)
108
111
} else {
109
- RustcVersion {
112
+ Availability :: Since ( RustcVersion {
110
113
major : 1 ,
111
114
minor : 0 ,
112
115
patch : 0 ,
113
- }
116
+ } )
114
117
} ;
115
- self . is_above_msrv . insert ( def_id, version) ;
118
+ self . availability_cache . insert ( def_id, version) ;
116
119
version
117
120
}
118
121
@@ -143,7 +146,7 @@ impl IncompatibleMsrv {
143
146
144
147
if ( self . check_in_tests || !is_in_test ( cx. tcx , node) )
145
148
&& let Some ( current) = self . msrv . current ( cx)
146
- && let version = self . get_def_id_version ( cx. tcx , def_id)
149
+ && let Availability :: Since ( version) = self . get_def_id_availability ( cx. tcx , def_id)
147
150
&& version > current
148
151
{
149
152
span_lint_and_then (
0 commit comments