@@ -11,8 +11,8 @@ use rustc_hir as hir;
1111use rustc_hir:: intravisit:: { walk_body, walk_expr, walk_ty, FnKind , NestedVisitorMap , Visitor } ;
1212use rustc_hir:: {
1313 BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericParamKind , HirId , ImplItem ,
14- ImplItemKind , Item , ItemKind , Lifetime , Local , MatchSource , MutTy , Mutability , QPath , Stmt , StmtKind , TraitFn ,
15- TraitItem , TraitItemKind , TyKind , UnOp ,
14+ ImplItemKind , Item , ItemKind , Lifetime , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind ,
15+ TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
1616} ;
1717use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
1818use rustc_middle:: hir:: map:: Map ;
@@ -31,8 +31,8 @@ use crate::utils::paths;
3131use crate :: utils:: {
3232 clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item,
3333 last_path_segment, match_def_path, match_path, method_chain_args, multispan_sugg, numeric_literal:: NumericLiteral ,
34- qpath_res, sext, snippet, snippet_block_with_applicability , snippet_opt, snippet_with_applicability,
35- snippet_with_macro_callsite , span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
34+ qpath_res, reindent_multiline , sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite ,
35+ span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
3636} ;
3737
3838declare_clippy_lint ! {
@@ -805,6 +805,45 @@ impl<'tcx> LateLintPass<'tcx> for UnitArg {
805805 }
806806}
807807
808+ fn fmt_stmts_and_call (
809+ cx : & LateContext < ' _ > ,
810+ call_expr : & Expr < ' _ > ,
811+ call_snippet : & str ,
812+ args_snippets : & [ impl AsRef < str > ] ,
813+ non_empty_block_args_snippets : & [ impl AsRef < str > ] ,
814+ ) -> String {
815+ let call_expr_indent = indent_of ( cx, call_expr. span ) . unwrap_or ( 0 ) ;
816+ let call_snippet_with_replacements = args_snippets
817+ . iter ( )
818+ . fold ( call_snippet. to_owned ( ) , |acc, arg| acc. replacen ( arg. as_ref ( ) , "()" , 1 ) ) ;
819+
820+ let mut stmts_and_call = non_empty_block_args_snippets
821+ . iter ( )
822+ . map ( |it| it. as_ref ( ) . to_owned ( ) )
823+ . collect :: < Vec < _ > > ( ) ;
824+ stmts_and_call. push ( call_snippet_with_replacements) ;
825+ stmts_and_call = stmts_and_call
826+ . into_iter ( )
827+ . map ( |v| reindent_multiline ( v. into ( ) , true , Some ( call_expr_indent) ) . into_owned ( ) )
828+ . collect ( ) ;
829+
830+ let mut stmts_and_call_snippet = stmts_and_call. join ( & format ! ( "{}{}" , ";\n " , " " . repeat( call_expr_indent) ) ) ;
831+ // expr is not in a block statement or result expression position, wrap in a block
832+ let parent_node = cx. tcx . hir ( ) . find ( cx. tcx . hir ( ) . get_parent_node ( call_expr. hir_id ) ) ;
833+ if !matches ! ( parent_node, Some ( Node :: Block ( _) ) ) && !matches ! ( parent_node, Some ( Node :: Stmt ( _) ) ) {
834+ let block_indent = call_expr_indent + 4 ;
835+ stmts_and_call_snippet =
836+ reindent_multiline ( stmts_and_call_snippet. into ( ) , true , Some ( block_indent) ) . into_owned ( ) ;
837+ stmts_and_call_snippet = format ! (
838+ "{{\n {}{}\n {}}}" ,
839+ " " . repeat( block_indent) ,
840+ & stmts_and_call_snippet,
841+ " " . repeat( call_expr_indent)
842+ ) ;
843+ }
844+ stmts_and_call_snippet
845+ }
846+
808847fn lint_unit_args ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , args_to_recover : & [ & Expr < ' _ > ] ) {
809848 let mut applicability = Applicability :: MachineApplicable ;
810849 let ( singular, plural) = if args_to_recover. len ( ) > 1 {
@@ -847,43 +886,52 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
847886 Applicability :: MaybeIncorrect ,
848887 ) ;
849888 or = "or " ;
889+ applicability = Applicability :: MaybeIncorrect ;
850890 } ) ;
851- let sugg = args_to_recover
891+
892+ let arg_snippets: Vec < String > = args_to_recover
893+ . iter ( )
894+ . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
895+ . collect ( ) ;
896+ let arg_snippets_without_empty_blocks: Vec < String > = args_to_recover
852897 . iter ( )
853898 . filter ( |arg| !is_empty_block ( arg) )
854- . enumerate ( )
855- . map ( |( i, arg) | {
856- let indent = if i == 0 {
857- 0
858- } else {
859- indent_of ( cx, expr. span ) . unwrap_or ( 0 )
860- } ;
861- format ! (
862- "{}{};" ,
863- " " . repeat( indent) ,
864- snippet_block_with_applicability( cx, arg. span, ".." , Some ( expr. span) , & mut applicability)
865- )
866- } )
867- . collect :: < Vec < String > > ( ) ;
868- let mut and = "" ;
869- if !sugg. is_empty ( ) {
870- let plural = if sugg. len ( ) > 1 { "s" } else { "" } ;
871- db. span_suggestion (
872- expr. span . with_hi ( expr. span . lo ( ) ) ,
873- & format ! ( "{}move the expression{} in front of the call..." , or, plural) ,
874- format ! ( "{}\n " , sugg. join( "\n " ) ) ,
875- applicability,
899+ . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
900+ . collect ( ) ;
901+
902+ if let Some ( call_snippet) = snippet_opt ( cx, expr. span ) {
903+ let sugg = fmt_stmts_and_call (
904+ cx,
905+ expr,
906+ & call_snippet,
907+ & arg_snippets,
908+ & arg_snippets_without_empty_blocks,
876909 ) ;
877- and = "...and "
910+
911+ if arg_snippets_without_empty_blocks. is_empty ( ) {
912+ db. multipart_suggestion (
913+ & format ! ( "use {}unit literal{} instead" , singular, plural) ,
914+ args_to_recover
915+ . iter ( )
916+ . map ( |arg| ( arg. span , "()" . to_string ( ) ) )
917+ . collect :: < Vec < _ > > ( ) ,
918+ applicability,
919+ ) ;
920+ } else {
921+ let plural = arg_snippets_without_empty_blocks. len ( ) > 1 ;
922+ let empty_or_s = if plural { "s" } else { "" } ;
923+ let it_or_them = if plural { "them" } else { "it" } ;
924+ db. span_suggestion (
925+ expr. span ,
926+ & format ! (
927+ "{}move the expression{} in front of the call and replace {} with the unit literal `()`" ,
928+ or, empty_or_s, it_or_them
929+ ) ,
930+ sugg,
931+ applicability,
932+ ) ;
933+ }
878934 }
879- db. multipart_suggestion (
880- & format ! ( "{}use {}unit literal{} instead" , and, singular, plural) ,
881- args_to_recover
882- . iter ( )
883- . map ( |arg| ( arg. span , "()" . to_string ( ) ) )
884- . collect :: < Vec < _ > > ( ) ,
885- applicability,
886- ) ;
887935 } ,
888936 ) ;
889937}
@@ -2058,6 +2106,7 @@ impl PartialOrd for FullInt {
20582106 } )
20592107 }
20602108}
2109+
20612110impl Ord for FullInt {
20622111 #[ must_use]
20632112 fn cmp ( & self , other : & Self ) -> Ordering {
0 commit comments