@@ -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,20 +21,22 @@ 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 } ;
26
27
27
28
use crate :: consts:: { constant, Constant } ;
28
29
use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
29
30
use crate :: utils:: usage:: mutated_variables;
30
31
use crate :: utils:: {
31
- contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
32
- is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
33
- match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
34
- 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 ,
32
+ contains_ty, get_arg_name, get_inner_attr, get_parent_expr, get_trait_def_id, has_iter_method, higher,
33
+ implements_trait, in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment,
34
+ match_def_path, match_qpath, match_trait_method, match_type, match_var, meets_msrv, method_calls,
35
+ method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability,
36
+ snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg,
37
+ walk_ptrs_ty_depth, SpanlessEq ,
36
38
} ;
39
+ use semver:: { Version , VersionReq } ;
37
40
38
41
declare_clippy_lint ! {
39
42
/// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s.
@@ -1404,7 +1407,18 @@ declare_clippy_lint! {
1404
1407
"use `.collect()` instead of `::from_iter()`"
1405
1408
}
1406
1409
1407
- declare_lint_pass ! ( Methods => [
1410
+ pub struct Methods {
1411
+ msrv : Option < VersionReq > ,
1412
+ }
1413
+
1414
+ impl Methods {
1415
+ #[ must_use]
1416
+ pub fn new ( msrv : Option < VersionReq > ) -> Self {
1417
+ Self { msrv }
1418
+ }
1419
+ }
1420
+
1421
+ impl_lint_pass ! ( Methods => [
1408
1422
UNWRAP_USED ,
1409
1423
EXPECT_USED ,
1410
1424
SHOULD_IMPLEMENT_TRAIT ,
@@ -1531,8 +1545,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1531
1545
check_pointer_offset ( cx, expr, arg_lists[ 0 ] )
1532
1546
} ,
1533
1547
[ "is_file" , ..] => lint_filetype_is_file ( cx, expr, arg_lists[ 0 ] ) ,
1534
- [ "map" , "as_ref" ] => lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , false ) ,
1535
- [ "map" , "as_mut" ] => lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , true ) ,
1548
+ [ "map" , "as_ref" ] => {
1549
+ lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , false , self . msrv . as_ref ( ) )
1550
+ } ,
1551
+ [ "map" , "as_mut" ] => {
1552
+ lint_option_as_ref_deref ( cx, expr, arg_lists[ 1 ] , arg_lists[ 0 ] , true , self . msrv . as_ref ( ) )
1553
+ } ,
1536
1554
[ "unwrap_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "unwrap_or" ) ,
1537
1555
[ "get_or_insert_with" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "get_or_insert" ) ,
1538
1556
[ "ok_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "ok_or" ) ,
@@ -1738,6 +1756,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1738
1756
}
1739
1757
}
1740
1758
}
1759
+
1760
+ extract_msrv_attr ! ( LateContext ) ;
1741
1761
}
1742
1762
1743
1763
/// Checks for the `OR_FUN_CALL` lint.
@@ -3453,14 +3473,27 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
3453
3473
) ;
3454
3474
}
3455
3475
3476
+ const OPTION_AS_REF_DEREF_MSRV : Version = Version {
3477
+ major : 1 ,
3478
+ minor : 40 ,
3479
+ patch : 0 ,
3480
+ pre : Vec :: new ( ) ,
3481
+ build : Vec :: new ( ) ,
3482
+ } ;
3483
+
3456
3484
/// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
3457
3485
fn lint_option_as_ref_deref < ' tcx > (
3458
3486
cx : & LateContext < ' tcx > ,
3459
3487
expr : & hir:: Expr < ' _ > ,
3460
3488
as_ref_args : & [ hir:: Expr < ' _ > ] ,
3461
3489
map_args : & [ hir:: Expr < ' _ > ] ,
3462
3490
is_mut : bool ,
3491
+ msrv : Option < & VersionReq > ,
3463
3492
) {
3493
+ if !meets_msrv ( msrv, & OPTION_AS_REF_DEREF_MSRV ) {
3494
+ return ;
3495
+ }
3496
+
3464
3497
let same_mutability = |m| ( is_mut && m == & hir:: Mutability :: Mut ) || ( !is_mut && m == & hir:: Mutability :: Not ) ;
3465
3498
3466
3499
let option_ty = cx. typeck_results ( ) . expr_ty ( & as_ref_args[ 0 ] ) ;
0 commit comments