@@ -12,6 +12,7 @@ use std::iter;
1212use bind_instead_of_map:: BindInsteadOfMap ;
1313use if_chain:: if_chain;
1414use rustc_ast:: ast;
15+ use rustc_ast:: ast:: Attribute ;
1516use rustc_errors:: Applicability ;
1617use rustc_hir as hir;
1718use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -20,20 +21,22 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
2021use rustc_middle:: hir:: map:: Map ;
2122use rustc_middle:: lint:: in_external_macro;
2223use 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 } ;
2425use rustc_span:: source_map:: Span ;
2526use rustc_span:: symbol:: { sym, SymbolStr } ;
2627
2728use crate :: consts:: { constant, Constant } ;
2829use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
2930use crate :: utils:: usage:: mutated_variables;
3031use 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 ,
3638} ;
39+ use semver:: { Version , VersionReq } ;
3740
3841declare_clippy_lint ! {
3942 /// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s.
@@ -1404,7 +1407,18 @@ declare_clippy_lint! {
14041407 "use `.collect()` instead of `::from_iter()`"
14051408}
14061409
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 => [
14081422 UNWRAP_USED ,
14091423 EXPECT_USED ,
14101424 SHOULD_IMPLEMENT_TRAIT ,
@@ -1531,8 +1545,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
15311545 check_pointer_offset ( cx, expr, arg_lists[ 0 ] )
15321546 } ,
15331547 [ "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+ } ,
15361554 [ "unwrap_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "unwrap_or" ) ,
15371555 [ "get_or_insert_with" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "get_or_insert" ) ,
15381556 [ "ok_or_else" , ..] => unnecessary_lazy_eval:: lint ( cx, expr, arg_lists[ 0 ] , "ok_or" ) ,
@@ -1738,6 +1756,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
17381756 }
17391757 }
17401758 }
1759+
1760+ extract_msrv_attr ! ( LateContext ) ;
17411761}
17421762
17431763/// Checks for the `OR_FUN_CALL` lint.
@@ -3453,14 +3473,27 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
34533473 ) ;
34543474}
34553475
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+
34563484/// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
34573485fn lint_option_as_ref_deref < ' tcx > (
34583486 cx : & LateContext < ' tcx > ,
34593487 expr : & hir:: Expr < ' _ > ,
34603488 as_ref_args : & [ hir:: Expr < ' _ > ] ,
34613489 map_args : & [ hir:: Expr < ' _ > ] ,
34623490 is_mut : bool ,
3491+ msrv : Option < & VersionReq > ,
34633492) {
3493+ if !meets_msrv ( msrv, & OPTION_AS_REF_DEREF_MSRV ) {
3494+ return ;
3495+ }
3496+
34643497 let same_mutability = |m| ( is_mut && m == & hir:: Mutability :: Mut ) || ( !is_mut && m == & hir:: Mutability :: Not ) ;
34653498
34663499 let option_ty = cx. typeck_results ( ) . expr_ty ( & as_ref_args[ 0 ] ) ;
0 commit comments