@@ -33,6 +33,7 @@ mod ok_expect;
33
33
mod option_as_ref_deref;
34
34
mod option_map_or_none;
35
35
mod option_map_unwrap_or;
36
+ mod or_fun_call;
36
37
mod search_is_some;
37
38
mod single_char_insert_string;
38
39
mod single_char_pattern;
@@ -66,12 +67,11 @@ use rustc_span::source_map::Span;
66
67
use rustc_span:: symbol:: { sym, SymbolStr } ;
67
68
use rustc_typeck:: hir_ty_to_ty;
68
69
69
- use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
70
70
use crate :: utils:: {
71
71
contains_return, contains_ty, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of,
72
- is_type_diagnostic_item, iter_input_pats, last_path_segment , match_def_path, match_qpath, match_type , method_calls ,
73
- method_chain_args , paths , return_ty, single_segment_path, snippet, snippet_with_applicability,
74
- snippet_with_macro_callsite , span_lint , span_lint_and_help , span_lint_and_sugg, SpanlessEq ,
72
+ is_type_diagnostic_item, iter_input_pats, match_def_path, match_qpath, method_calls , method_chain_args , paths ,
73
+ return_ty, single_segment_path, snippet, snippet_with_applicability, span_lint , span_lint_and_help ,
74
+ span_lint_and_sugg, SpanlessEq ,
75
75
} ;
76
76
77
77
declare_clippy_lint ! {
@@ -1778,7 +1778,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1778
1778
}
1779
1779
} ,
1780
1780
hir:: ExprKind :: MethodCall ( ref method_call, ref method_span, ref args, _) => {
1781
- lint_or_fun_call ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
1781
+ or_fun_call :: check ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
1782
1782
lint_expect_fun_call ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
1783
1783
1784
1784
let self_ty = cx. typeck_results ( ) . expr_ty_adjusted ( & args[ 0 ] ) ;
@@ -1973,164 +1973,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1973
1973
extract_msrv_attr ! ( LateContext ) ;
1974
1974
}
1975
1975
1976
- /// Checks for the `OR_FUN_CALL` lint.
1977
- #[ allow( clippy:: too_many_lines) ]
1978
- fn lint_or_fun_call < ' tcx > (
1979
- cx : & LateContext < ' tcx > ,
1980
- expr : & hir:: Expr < ' _ > ,
1981
- method_span : Span ,
1982
- name : & str ,
1983
- args : & ' tcx [ hir:: Expr < ' _ > ] ,
1984
- ) {
1985
- /// Checks for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
1986
- fn check_unwrap_or_default (
1987
- cx : & LateContext < ' _ > ,
1988
- name : & str ,
1989
- fun : & hir:: Expr < ' _ > ,
1990
- self_expr : & hir:: Expr < ' _ > ,
1991
- arg : & hir:: Expr < ' _ > ,
1992
- or_has_args : bool ,
1993
- span : Span ,
1994
- ) -> bool {
1995
- if_chain ! {
1996
- if !or_has_args;
1997
- if name == "unwrap_or" ;
1998
- if let hir:: ExprKind :: Path ( ref qpath) = fun. kind;
1999
- let path = & * last_path_segment( qpath) . ident. as_str( ) ;
2000
- if [ "default" , "new" ] . contains( & path) ;
2001
- let arg_ty = cx. typeck_results( ) . expr_ty( arg) ;
2002
- if let Some ( default_trait_id) = get_trait_def_id( cx, & paths:: DEFAULT_TRAIT ) ;
2003
- if implements_trait( cx, arg_ty, default_trait_id, & [ ] ) ;
2004
-
2005
- then {
2006
- let mut applicability = Applicability :: MachineApplicable ;
2007
- span_lint_and_sugg(
2008
- cx,
2009
- OR_FUN_CALL ,
2010
- span,
2011
- & format!( "use of `{}` followed by a call to `{}`" , name, path) ,
2012
- "try this" ,
2013
- format!(
2014
- "{}.unwrap_or_default()" ,
2015
- snippet_with_applicability( cx, self_expr. span, ".." , & mut applicability)
2016
- ) ,
2017
- applicability,
2018
- ) ;
2019
-
2020
- true
2021
- } else {
2022
- false
2023
- }
2024
- }
2025
- }
2026
-
2027
- /// Checks for `*or(foo())`.
2028
- #[ allow( clippy:: too_many_arguments) ]
2029
- fn check_general_case < ' tcx > (
2030
- cx : & LateContext < ' tcx > ,
2031
- name : & str ,
2032
- method_span : Span ,
2033
- self_expr : & hir:: Expr < ' _ > ,
2034
- arg : & ' tcx hir:: Expr < ' _ > ,
2035
- span : Span ,
2036
- // None if lambda is required
2037
- fun_span : Option < Span > ,
2038
- ) {
2039
- // (path, fn_has_argument, methods, suffix)
2040
- static KNOW_TYPES : [ ( & [ & str ] , bool , & [ & str ] , & str ) ; 4 ] = [
2041
- ( & paths:: BTREEMAP_ENTRY , false , & [ "or_insert" ] , "with" ) ,
2042
- ( & paths:: HASHMAP_ENTRY , false , & [ "or_insert" ] , "with" ) ,
2043
- ( & paths:: OPTION , false , & [ "map_or" , "ok_or" , "or" , "unwrap_or" ] , "else" ) ,
2044
- ( & paths:: RESULT , true , & [ "or" , "unwrap_or" ] , "else" ) ,
2045
- ] ;
2046
-
2047
- if let hir:: ExprKind :: MethodCall ( ref path, _, ref args, _) = & arg. kind {
2048
- if path. ident . as_str ( ) == "len" {
2049
- let ty = cx. typeck_results ( ) . expr_ty ( & args[ 0 ] ) . peel_refs ( ) ;
2050
-
2051
- match ty. kind ( ) {
2052
- ty:: Slice ( _) | ty:: Array ( _, _) => return ,
2053
- _ => ( ) ,
2054
- }
2055
-
2056
- if is_type_diagnostic_item ( cx, ty, sym:: vec_type) {
2057
- return ;
2058
- }
2059
- }
2060
- }
2061
-
2062
- if_chain ! {
2063
- if KNOW_TYPES . iter( ) . any( |k| k. 2 . contains( & name) ) ;
2064
-
2065
- if is_lazyness_candidate( cx, arg) ;
2066
- if !contains_return( & arg) ;
2067
-
2068
- let self_ty = cx. typeck_results( ) . expr_ty( self_expr) ;
2069
-
2070
- if let Some ( & ( _, fn_has_arguments, poss, suffix) ) =
2071
- KNOW_TYPES . iter( ) . find( |&&i| match_type( cx, self_ty, i. 0 ) ) ;
2072
-
2073
- if poss. contains( & name) ;
2074
-
2075
- then {
2076
- let macro_expanded_snipped;
2077
- let sugg: Cow <' _, str > = {
2078
- let ( snippet_span, use_lambda) = match ( fn_has_arguments, fun_span) {
2079
- ( false , Some ( fun_span) ) => ( fun_span, false ) ,
2080
- _ => ( arg. span, true ) ,
2081
- } ;
2082
- let snippet = {
2083
- let not_macro_argument_snippet = snippet_with_macro_callsite( cx, snippet_span, ".." ) ;
2084
- if not_macro_argument_snippet == "vec![]" {
2085
- macro_expanded_snipped = snippet( cx, snippet_span, ".." ) ;
2086
- match macro_expanded_snipped. strip_prefix( "$crate::vec::" ) {
2087
- Some ( stripped) => Cow :: from( stripped) ,
2088
- None => macro_expanded_snipped
2089
- }
2090
- }
2091
- else {
2092
- not_macro_argument_snippet
2093
- }
2094
- } ;
2095
-
2096
- if use_lambda {
2097
- let l_arg = if fn_has_arguments { "_" } else { "" } ;
2098
- format!( "|{}| {}" , l_arg, snippet) . into( )
2099
- } else {
2100
- snippet
2101
- }
2102
- } ;
2103
- let span_replace_word = method_span. with_hi( span. hi( ) ) ;
2104
- span_lint_and_sugg(
2105
- cx,
2106
- OR_FUN_CALL ,
2107
- span_replace_word,
2108
- & format!( "use of `{}` followed by a function call" , name) ,
2109
- "try this" ,
2110
- format!( "{}_{}({})" , name, suffix, sugg) ,
2111
- Applicability :: HasPlaceholders ,
2112
- ) ;
2113
- }
2114
- }
2115
- }
2116
-
2117
- if args. len ( ) == 2 {
2118
- match args[ 1 ] . kind {
2119
- hir:: ExprKind :: Call ( ref fun, ref or_args) => {
2120
- let or_has_args = !or_args. is_empty ( ) ;
2121
- if !check_unwrap_or_default ( cx, name, fun, & args[ 0 ] , & args[ 1 ] , or_has_args, expr. span ) {
2122
- let fun_span = if or_has_args { None } else { Some ( fun. span ) } ;
2123
- check_general_case ( cx, name, method_span, & args[ 0 ] , & args[ 1 ] , expr. span , fun_span) ;
2124
- }
2125
- } ,
2126
- hir:: ExprKind :: Index ( ..) | hir:: ExprKind :: MethodCall ( ..) => {
2127
- check_general_case ( cx, name, method_span, & args[ 0 ] , & args[ 1 ] , expr. span , None ) ;
2128
- } ,
2129
- _ => { } ,
2130
- }
2131
- }
2132
- }
2133
-
2134
1976
/// Checks for the `EXPECT_FUN_CALL` lint.
2135
1977
#[ allow( clippy:: too_many_lines) ]
2136
1978
fn lint_expect_fun_call (
0 commit comments