1- use clippy_utils:: diagnostics:: span_lint_and_sugg ;
1+ use clippy_utils:: diagnostics:: span_lint_and_then ;
22use clippy_utils:: ty:: is_type_diagnostic_item;
3- use clippy_utils:: { is_expr_untyped_identity_function, is_trait_method, path_to_local} ;
4- use rustc_ast:: BindingMode ;
3+ use clippy_utils:: { is_expr_untyped_identity_function, is_mutable, is_trait_method, path_to_local} ;
54use rustc_errors:: Applicability ;
65use rustc_hir:: { self as hir, Node , PatKind } ;
76use rustc_lint:: LateContext ;
@@ -23,26 +22,47 @@ pub(super) fn check(
2322 || is_type_diagnostic_item ( cx, caller_ty, sym:: Result )
2423 || is_type_diagnostic_item ( cx, caller_ty, sym:: Option ) )
2524 && is_expr_untyped_identity_function ( cx, map_arg)
26- && let Some ( sugg_span ) = expr. span . trim_start ( caller. span )
25+ && let Some ( call_span ) = expr. span . trim_start ( caller. span )
2726 {
28- // If the result of `.map(identity)` is used as a mutable reference,
29- // the caller must not be an immutable binding.
30- if cx. typeck_results ( ) . expr_ty_adjusted ( expr) . is_mutable_ptr ( )
31- && let Some ( hir_id) = path_to_local ( caller)
32- && let Node :: Pat ( pat) = cx. tcx . hir_node ( hir_id)
33- && !matches ! ( pat. kind, PatKind :: Binding ( BindingMode :: MUT , ..) )
34- {
35- return ;
27+ let mut sugg = vec ! [ ( call_span, String :: new( ) ) ] ;
28+ let mut apply = true ;
29+ if !is_mutable ( cx, caller) {
30+ if let Some ( hir_id) = path_to_local ( caller)
31+ && let Node :: Pat ( pat) = cx. tcx . hir_node ( hir_id)
32+ && let PatKind :: Binding ( _, _, ident, _) = pat. kind
33+ {
34+ sugg. push ( ( ident. span . shrink_to_lo ( ) , String :: from ( "mut " ) ) ) ;
35+ } else {
36+ // If we can't make the binding mutable, make the suggestion `Unspecified` to prevent it from being
37+ // automatically applied, and add a complementary help message.
38+ apply = false ;
39+ }
3640 }
3741
38- span_lint_and_sugg (
42+ let method_requiring_mut = String :: from ( "random_method" ) ; // TODO
43+
44+ span_lint_and_then (
3945 cx,
4046 MAP_IDENTITY ,
41- sugg_span ,
47+ call_span ,
4248 "unnecessary map of the identity function" ,
43- format ! ( "remove the call to `{name}`" ) ,
44- String :: new ( ) ,
45- Applicability :: MachineApplicable ,
49+ |diag| {
50+ diag. multipart_suggestion (
51+ format ! ( "remove the call to `{name}`" ) ,
52+ sugg,
53+ if apply {
54+ Applicability :: MachineApplicable
55+ } else {
56+ Applicability :: Unspecified
57+ } ,
58+ ) ;
59+ if !apply {
60+ diag. span_note (
61+ caller. span ,
62+ format ! ( "this must be made mutable to use `{method_requiring_mut}`" ) ,
63+ ) ;
64+ }
65+ } ,
4666 ) ;
4767 }
4868}
0 commit comments