@@ -12,6 +12,7 @@ use std::iter;
12
12
use bind_instead_of_map:: BindInsteadOfMap ;
13
13
use if_chain:: if_chain;
14
14
use rustc_ast:: ast;
15
+ use rustc_ast:: ast:: Attribute ;
15
16
use rustc_errors:: Applicability ;
16
17
use rustc_hir as hir;
17
18
use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -20,9 +21,10 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
20
21
use rustc_middle:: hir:: map:: Map ;
21
22
use rustc_middle:: lint:: in_external_macro;
22
23
use rustc_middle:: ty:: { self , TraitRef , Ty , TyS } ;
23
- use rustc_session:: { declare_lint_pass , declare_tool_lint } ;
24
+ use rustc_session:: { declare_tool_lint , impl_lint_pass } ;
24
25
use rustc_span:: source_map:: Span ;
25
26
use rustc_span:: symbol:: { sym, SymbolStr } ;
27
+ use semver:: Version ;
26
28
27
29
use crate :: consts:: { constant, Constant } ;
28
30
use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
@@ -32,7 +34,8 @@ use crate::utils::{
32
34
is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
33
35
match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
34
36
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
35
- span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq ,
37
+ span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth,
38
+ LimitStack , SpanlessEq ,
36
39
} ;
37
40
38
41
declare_clippy_lint ! {
@@ -1369,7 +1372,20 @@ declare_clippy_lint! {
1369
1372
"using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`"
1370
1373
}
1371
1374
1372
- declare_lint_pass ! ( Methods => [
1375
+ pub struct Methods {
1376
+ msrv_stack : LimitStack < String > ,
1377
+ }
1378
+
1379
+ impl Methods {
1380
+ #[ must_use]
1381
+ pub fn new ( msrv : String ) -> Self {
1382
+ Self {
1383
+ msrv_stack : LimitStack :: new ( msrv. clone ( ) ) ,
1384
+ }
1385
+ }
1386
+ }
1387
+
1388
+ impl_lint_pass ! ( Methods => [
1373
1389
UNWRAP_USED ,
1374
1390
EXPECT_USED ,
1375
1391
SHOULD_IMPLEMENT_TRAIT ,
@@ -1495,8 +1511,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1495
1511
check_pointer_offset ( cx, expr, arg_lists[ 0 ] )
1496
1512
} ,
1497
1513
[ "is_file" , ..] => lint_filetype_is_file ( cx, expr, arg_lists[ 0 ] ) ,
1498
- [ "map" , "as_ref" ] => lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , false ) ,
1499
- [ "map" , "as_mut" ] => lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , true ) ,
1514
+ [ "map" , "as_ref" ] => {
1515
+ lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , false , & self . msrv_stack )
1516
+ } ,
1517
+ [ "map" , "as_mut" ] => lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , true , & self . msrv_stack ) ,
1500
1518
[ "unwrap_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "unwrap_or" ) ,
1501
1519
[ "get_or_insert_with" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "get_or_insert" ) ,
1502
1520
[ "ok_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "ok_or" ) ,
@@ -1693,6 +1711,14 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1693
1711
}
1694
1712
}
1695
1713
}
1714
+
1715
+ fn enter_lint_attrs ( & mut self , cx : & LateContext < ' tcx > , attrs : & ' tcx [ Attribute ] ) {
1716
+ self . msrv_stack . push_attrs ( cx. sess ( ) , attrs, "msrv" ) ;
1717
+ }
1718
+
1719
+ fn exit_lint_attrs ( & mut self , cx : & LateContext < ' tcx > , attrs : & ' tcx [ Attribute ] ) {
1720
+ self . msrv_stack . pop_attrs ( cx. sess ( ) , attrs, "msrv" ) ;
1721
+ }
1696
1722
}
1697
1723
1698
1724
/// Checks for the `OR_FUN_CALL` lint.
@@ -3364,14 +3390,21 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
3364
3390
) ;
3365
3391
}
3366
3392
3393
+ const OPTION_AS_REF_DEREF_MSRV : & str = "1.40.0" ;
3394
+
3367
3395
/// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
3368
3396
fn lint_option_as_ref_deref < ' tcx > (
3369
3397
cx : & LateContext < ' tcx > ,
3370
3398
expr : & hir:: Expr < ' _ > ,
3371
3399
as_ref_args : & [ hir:: Expr < ' _ > ] ,
3372
3400
map_args : & [ hir:: Expr < ' _ > ] ,
3373
3401
is_mut : bool ,
3402
+ msrv_stack : & LimitStack < String > ,
3374
3403
) {
3404
+ if Version :: parse ( & msrv_stack. limit ( ) ) < Version :: parse ( OPTION_AS_REF_DEREF_MSRV ) {
3405
+ return ;
3406
+ }
3407
+
3375
3408
let same_mutability = |m| ( is_mut && m == & hir:: Mutability :: Mut ) || ( !is_mut && m == & hir:: Mutability :: Not ) ;
3376
3409
3377
3410
let option_ty = cx. typeck_results ( ) . expr_ty ( & as_ref_args[ 0 ] ) ;
0 commit comments