Skip to content

Commit 4fe3727

Browse files
committed
Auto merge of #9701 - smoelius:improve-possible-borrower, r=Jarcho
Improve `possible_borrower` This PR makes several improvements to `clippy_uitls::mir::possible_borrower`. These changes benefit both `needless_borrow` and `redundant clone`. 1. **Use the compiler's `MaybeStorageLive` analysis** I could spot not functional differences between the one in the compiler and the one in Clippy's repository. So, I removed the latter in favor of the the former. 2. **Make `PossibleBorrower` a dataflow analysis instead of a visitor** The main benefit of this change is that allows `possible_borrower` to take advantage of statements' relative locations, which is easier to do in an analysis than in a visitor. This is easier to illustrate with an example, so consider this one: ```rust fn foo(cx: &LateContext<'_>, lint: &'static Lint) { cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new())); // ^ } ``` We would like to flag the `&` pointed to by the `^` for removal. `foo`'s MIR begins like this: ```rust fn span_lint::foo::{closure#0}(_1: [closure@$DIR/needless_borrow.rs:396:68: 396:74], _2: &mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()>) -> &mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()> { debug diag => _2; // in scope 0 at $DIR/needless_borrow.rs:396:69: 396:73 let mut _0: &mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()>; // return place in scope 0 at $DIR/needless_borrow.rs:396:75: 396:75 let mut _3: &mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()>; // in scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 let mut _4: &mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()>; // in scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 let mut _5: &std::string::String; // in scope 0 at $DIR/needless_borrow.rs:396:85: 396:99 let _6: std::string::String; // in scope 0 at $DIR/needless_borrow.rs:396:86: 396:99 bb0: { StorageLive(_3); // scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 StorageLive(_4); // scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 _4 = &mut (*_2); // scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 StorageLive(_5); // scope 0 at $DIR/needless_borrow.rs:396:85: 396:99 StorageLive(_6); // scope 0 at $DIR/needless_borrow.rs:396:86: 396:99 _6 = std::string::String::new() -> bb1; // scope 0 at $DIR/needless_borrow.rs:396:86: 396:99 // mir::Constant // + span: $DIR/needless_borrow.rs:396:86: 396:97 // + literal: Const { ty: fn() -> std::string::String {std::string::String::new}, val: Value(<ZST>) } } bb1: { _5 = &_6; // scope 0 at $DIR/needless_borrow.rs:396:85: 396:99 _3 = rustc_errors::diagnostic_builder::DiagnosticBuilder::<'_, ()>::note::<&std::string::String>(move _4, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/needless_borrow.rs:396:75: 396:100 // mir::Constant // + span: $DIR/needless_borrow.rs:396:80: 396:84 // + literal: Const { ty: for<'a> fn(&'a mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()>, &std::string::String) -> &'a mut rustc_errors::diagnostic_builder::DiagnosticBuilder<'_, ()> {rustc_errors::diagnostic_builder::DiagnosticBuilder::<'_, ()>::note::<&std::string::String>}, val: Value(<ZST>) } } ``` The call to `diag.note` appears in `bb1` on the line beginning with `_3 =`. The `String` is owned by `_6`. So, in the call to `diag.note`, we would like to know whether there are any references to `_6` besides `_5`. The old, visitor approach did not consider the relative locations of statements. So all borrows were treated the same, *even if they occurred after the location of interest*. For example, before the `_3 = ...` call, the possible borrowers of `_6` would be just `_5`. But after the call, the possible borrowers would include `_2`, `_3`, and `_4`. So, in a sense, the call from which we are try to remove the needless borrow is trying to prevent us from removing the needless borrow(!). With an analysis, things do not get so muddled. We can determine the set of possible borrowers at any specific location, e.g., using a `ResultsCursor`. 3. **Change `only_borrowers` to `at_most_borrowers`** `possible_borrowers` exposed a function `only_borrowers` that determined whether the borrowers of some local were *exactly* some set `S`. But, from what I can tell, this was overkill. For the lints that currently use `possible_borrower` (`needless_borrow` and `redundant_clone`), all we really want to know is whether there are borrowers *other than* those in `S`. (Put another way, we only care about the subset relation in one direction.) The new function `at_most_borrowers` takes this more tailored approach. 4. **Compute relations "on the fly" rather than using `transitive_relation`** The visitor would compute and store the transitive closure of the possible borrower relation for an entire MIR body. But with an analysis, there is effectively a different possible borrower relation at each location in the body. Computing and storing a transitive closure at each location would not be practical. So the new approach is to compute the transitive closure on the fly, as needed. But the new approach might actually be more efficient, as I now explain. In all current uses of `at_most_borrowers` (previously `only_borrowers`), the size of the set of borrowers `S` is at most 2. So you need only check at most three borrowers to determine whether the subset relation holds. That is, once you have found a third borrower, you can stop, since you know the relation cannot hold. Note that `transitive_relation` is still used by `clippy_uitls::mir::possible_origin` (a kind of "subroutine" of `possible_borrower`). cc: `@Jarcho` --- changelog: [`needless_borrow`], [`redundant_clone`]: Now track references better and detect more cases [#9701](#9701) <!-- changelog_checked -->
2 parents 8a6e6fd + 4dbd8ad commit 4fe3727

38 files changed

+277
-209
lines changed

clippy_lints/src/casts/cast_slice_different_sizes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
5454

5555
diag.span_suggestion(
5656
expr.span,
57-
&format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
57+
format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
5858
sugg,
5959
rustc_errors::Applicability::HasPlaceholders,
6060
);

clippy_lints/src/dereference.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>(
12821282
possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
12831283
}
12841284
let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
1285-
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
1286-
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
1287-
// itself. See the comment in that method for an explanation as to why.
1288-
possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
1285+
// If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
1286+
// reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
1287+
// borrower of itself. See the comment in that method for an explanation as to why.
1288+
possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
12891289
&& used_exactly_once(mir, place.local).unwrap_or(false)
12901290
} else {
12911291
false

clippy_lints/src/format_args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb
377377
call_site,
378378
&format!("`format!` in `{name}!` args"),
379379
|diag| {
380-
diag.help(&format!(
380+
diag.help(format!(
381381
"combine the `format!(..)` arguments with the outer `{name}!(..)` call"
382382
));
383383
diag.help("or consider changing `format!` to `format_args!`");

clippy_lints/src/large_enum_variant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
111111
);
112112
diag.span_label(
113113
def.variants[variants_size[1].ind].span,
114-
&if variants_size[1].fields_size.is_empty() {
114+
if variants_size[1].fields_size.is_empty() {
115115
"the second-largest variant carries no data at all".to_owned()
116116
} else {
117117
format!(

clippy_lints/src/len_zero.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ fn check_for_is_empty<'tcx>(
361361
db.span_note(span, "`is_empty` defined here");
362362
}
363363
if let Some(self_kind) = self_kind {
364-
db.note(&output.expected_sig(self_kind));
364+
db.note(output.expected_sig(self_kind));
365365
}
366366
});
367367
}

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
336336
Ok(Some(path)) => path,
337337
Ok(None) => return Conf::default(),
338338
Err(error) => {
339-
sess.struct_err(&format!("error finding Clippy's configuration file: {error}"))
339+
sess.struct_err(format!("error finding Clippy's configuration file: {error}"))
340340
.emit();
341341
return Conf::default();
342342
},

clippy_lints/src/loops/explicit_counter_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
7777
applicability,
7878
);
7979

80-
diag.note(&format!(
80+
diag.note(format!(
8181
"`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
8282
));
8383
},

clippy_lints/src/manual_async_fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
7676
let help = format!("make the function `async` and {ret_sugg}");
7777
diag.span_suggestion(
7878
header_span,
79-
&help,
79+
help,
8080
format!("async {}{ret_snip}", &header_snip[..ret_pos]),
8181
Applicability::MachineApplicable
8282
);

clippy_lints/src/manual_strip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
109109

110110
let test_span = expr.span.until(then.span);
111111
span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
112-
diag.span_note(test_span, &format!("the {kind_word} was tested here"));
112+
diag.span_note(test_span, format!("the {kind_word} was tested here"));
113113
multispan_sugg(
114114
diag,
115115
&format!("try using the `strip_{kind_word}` method"),

clippy_lints/src/methods/inefficient_to_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn check(
3636
expr.span,
3737
&format!("calling `to_string` on `{arg_ty}`"),
3838
|diag| {
39-
diag.help(&format!(
39+
diag.help(format!(
4040
"`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
4141
));
4242
let mut applicability = Applicability::MachineApplicable;

clippy_lints/src/methods/iter_skip_next.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
2929
application = Applicability::Unspecified;
3030
diag.span_help(
3131
pat.span,
32-
&format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
32+
format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
3333
);
3434
}
3535
}

clippy_lints/src/methods/option_map_unwrap_or.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
8484
suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, ")));
8585
}
8686

87-
diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability);
87+
diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability);
8888
});
8989
}
9090
}

clippy_lints/src/methods/str_splitn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn check_manual_split_once_indirect(
167167
};
168168
diag.span_suggestion_verbose(
169169
local.span,
170-
&format!("try `{r}split_once`"),
170+
format!("try `{r}split_once`"),
171171
format!("let ({lhs}, {rhs}) = {self_snip}.{r}split_once({pat_snip}){unwrap};"),
172172
app,
173173
);

clippy_lints/src/methods/unnecessary_lazy_eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
6262
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
6363
diag.span_suggestion(
6464
span,
65-
&format!("use `{simplify_using}(..)` instead"),
65+
format!("use `{simplify_using}(..)` instead"),
6666
format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
6767
applicability,
6868
);

clippy_lints/src/needless_late_init.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ fn check<'tcx>(
284284

285285
diag.span_suggestion(
286286
assign.lhs_span,
287-
&format!("declare `{binding_name}` here"),
287+
format!("declare `{binding_name}` here"),
288288
let_snippet,
289289
Applicability::MachineApplicable,
290290
);
@@ -304,7 +304,7 @@ fn check<'tcx>(
304304

305305
diag.span_suggestion_verbose(
306306
usage.stmt.span.shrink_to_lo(),
307-
&format!("declare `{binding_name}` here"),
307+
format!("declare `{binding_name}` here"),
308308
format!("{let_snippet} = "),
309309
applicability,
310310
);
@@ -335,7 +335,7 @@ fn check<'tcx>(
335335

336336
diag.span_suggestion_verbose(
337337
usage.stmt.span.shrink_to_lo(),
338-
&format!("declare `{binding_name}` here"),
338+
format!("declare `{binding_name}` here"),
339339
format!("{let_snippet} = "),
340340
applicability,
341341
);

clippy_lints/src/octal_escapes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
125125
if is_string { "string" } else { "byte string" }
126126
),
127127
|diag| {
128-
diag.help(&format!(
128+
diag.help(format!(
129129
"octal escapes are not supported, `\\0` is always a null {}",
130130
if is_string { "character" } else { "byte" }
131131
));
@@ -139,7 +139,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
139139
// suggestion 2: unambiguous null byte
140140
diag.span_suggestion(
141141
span,
142-
&format!(
142+
format!(
143143
"if the null {} is intended, disambiguate using",
144144
if is_string { "character" } else { "byte" }
145145
),

clippy_lints/src/operators/misrefactored_assign_op.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn lint_misrefactored_assign_op(
5050
let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r));
5151
diag.span_suggestion(
5252
expr.span,
53-
&format!(
53+
format!(
5454
"did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with",
5555
op.as_str()
5656
),

clippy_lints/src/redundant_clone.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
131131
// `res = clone(arg)` can be turned into `res = move arg;`
132132
// if `arg` is the only borrow of `cloned` at this point.
133133

134-
if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) {
134+
if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) {
135135
continue;
136136
}
137137

@@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
178178
// StorageDead(pred_arg);
179179
// res = to_path_buf(cloned);
180180
// ```
181-
if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) {
181+
if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) {
182182
continue;
183183
}
184184

clippy_lints/src/same_name_method.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
108108
|diag| {
109109
diag.span_note(
110110
trait_method_span,
111-
&format!("existing `{method_name}` defined here"),
111+
format!("existing `{method_name}` defined here"),
112112
);
113113
},
114114
);
@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
151151
// iterate on trait_spans?
152152
diag.span_note(
153153
trait_spans[0],
154-
&format!("existing `{method_name}` defined here"),
154+
format!("existing `{method_name}` defined here"),
155155
);
156156
},
157157
);

clippy_lints/src/swap.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
132132
applicability,
133133
);
134134
if !is_xor_based {
135-
diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?"));
135+
diag.note(format!("or maybe you should use `{sugg}::mem::replace`?"));
136136
}
137137
},
138138
);
@@ -214,7 +214,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
214214
Applicability::MaybeIncorrect,
215215
);
216216
diag.note(
217-
&format!("or maybe you should use `{sugg}::mem::replace`?")
217+
format!("or maybe you should use `{sugg}::mem::replace`?")
218218
);
219219
}
220220
});

clippy_lints/src/transmute/transmute_undefined_repr.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
7777
&format!("transmute from `{from_ty_orig}` which has an undefined layout"),
7878
|diag| {
7979
if from_ty_orig.peel_refs() != from_ty.peel_refs() {
80-
diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
80+
diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
8181
}
8282
},
8383
);
@@ -91,7 +91,7 @@ pub(super) fn check<'tcx>(
9191
&format!("transmute to `{to_ty_orig}` which has an undefined layout"),
9292
|diag| {
9393
if to_ty_orig.peel_refs() != to_ty.peel_refs() {
94-
diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
94+
diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
9595
}
9696
},
9797
);
@@ -119,16 +119,16 @@ pub(super) fn check<'tcx>(
119119
),
120120
|diag| {
121121
if let Some(same_adt_did) = same_adt_did {
122-
diag.note(&format!(
122+
diag.note(format!(
123123
"two instances of the same generic type (`{}`) may have different layouts",
124124
cx.tcx.item_name(same_adt_did)
125125
));
126126
} else {
127127
if from_ty_orig.peel_refs() != from_ty {
128-
diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
128+
diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
129129
}
130130
if to_ty_orig.peel_refs() != to_ty {
131-
diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
131+
diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
132132
}
133133
}
134134
},
@@ -146,7 +146,7 @@ pub(super) fn check<'tcx>(
146146
&format!("transmute from `{from_ty_orig}` which has an undefined layout"),
147147
|diag| {
148148
if from_ty_orig.peel_refs() != from_ty {
149-
diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
149+
diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
150150
}
151151
},
152152
);
@@ -163,7 +163,7 @@ pub(super) fn check<'tcx>(
163163
&format!("transmute into `{to_ty_orig}` which has an undefined layout"),
164164
|diag| {
165165
if to_ty_orig.peel_refs() != to_ty {
166-
diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
166+
diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
167167
}
168168
},
169169
);

clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
2424
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
2525
|diag| {
2626
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
27-
let sugg = arg.as_ty(&to_ty.to_string()).to_string();
27+
let sugg = arg.as_ty(to_ty.to_string()).to_string();
2828
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
2929
}
3030
},

clippy_lints/src/transmute/useless_transmute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(super) fn check<'tcx>(
6161
"transmute from an integer to a pointer",
6262
|diag| {
6363
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
64-
diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified);
64+
diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified);
6565
}
6666
},
6767
);

clippy_lints/src/types/redundant_allocation.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
3131
&format!("usage of `{outer_sym}<{generic_snippet}>`"),
3232
|diag| {
3333
diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability);
34-
diag.note(&format!(
34+
diag.note(format!(
3535
"`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
3636
));
3737
},
@@ -78,7 +78,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
7878
format!("{outer_sym}<{generic_snippet}>"),
7979
applicability,
8080
);
81-
diag.note(&format!(
81+
diag.note(format!(
8282
"`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
8383
));
8484
},
@@ -91,10 +91,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
9191
hir_ty.span,
9292
&format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
9393
|diag| {
94-
diag.note(&format!(
94+
diag.note(format!(
9595
"`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
9696
));
97-
diag.help(&format!(
97+
diag.help(format!(
9898
"consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`"
9999
));
100100
},

clippy_lints/src/unit_types/unit_arg.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
129129

130130
if arg_snippets_without_empty_blocks.is_empty() {
131131
db.multipart_suggestion(
132-
&format!("use {singular}unit literal{plural} instead"),
132+
format!("use {singular}unit literal{plural} instead"),
133133
args_to_recover
134134
.iter()
135135
.map(|arg| (arg.span, "()".to_string()))
@@ -142,7 +142,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
142142
let it_or_them = if plural { "them" } else { "it" };
143143
db.span_suggestion(
144144
expr.span,
145-
&format!(
145+
format!(
146146
"{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`"
147147
),
148148
sugg,

0 commit comments

Comments
 (0)