Skip to content

Commit 0781d5d

Browse files
authored
Rollup merge of #105019 - chenyukang:yukang/fix-104961-borrow, r=cjgillot
Add parentheses properly for borrowing suggestion Fixes #104961
2 parents 5a8dfd9 + 8f736a4 commit 0781d5d

File tree

4 files changed

+104
-7
lines changed

4 files changed

+104
-7
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+35-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_hir as hir;
1919
use rustc_hir::def::DefKind;
2020
use rustc_hir::def_id::DefId;
2121
use rustc_hir::intravisit::Visitor;
22+
use rustc_hir::is_range_literal;
2223
use rustc_hir::lang_items::LangItem;
2324
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
2425
use rustc_hir::{Expr, HirId};
@@ -1349,14 +1350,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13491350
Applicability::MaybeIncorrect,
13501351
);
13511352
} else {
1353+
// Issue #104961, we need to add parentheses properly for compond expressions
1354+
// for example, `x.starts_with("hi".to_string() + "you")`
1355+
// should be `x.starts_with(&("hi".to_string() + "you"))`
1356+
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
1357+
let body = self.tcx.hir().body(body_id);
1358+
let mut expr_finder = FindExprBySpan::new(span);
1359+
expr_finder.visit_expr(body.value);
1360+
let Some(expr) = expr_finder.result else { return false; };
1361+
let needs_parens = match expr.kind {
1362+
// parenthesize if needed (Issue #46756)
1363+
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
1364+
// parenthesize borrows of range literals (Issue #54505)
1365+
_ if is_range_literal(expr) => true,
1366+
_ => false,
1367+
};
1368+
13521369
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
1353-
err.span_suggestion_verbose(
1354-
span.shrink_to_lo(),
1355-
&format!(
1356-
"consider{} borrowing here",
1357-
if is_mut { " mutably" } else { "" }
1358-
),
1359-
format!("&{}", if is_mut { "mut " } else { "" }),
1370+
let span = if needs_parens { span } else { span.shrink_to_lo() };
1371+
let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" });
1372+
let sugg_msg = &format!(
1373+
"consider{} borrowing here",
1374+
if is_mut { " mutably" } else { "" }
1375+
);
1376+
1377+
let suggestions = if !needs_parens {
1378+
vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
1379+
} else {
1380+
vec![
1381+
(span.shrink_to_lo(), format!("{}(", sugg_prefix)),
1382+
(span.shrink_to_hi(), ")".to_string()),
1383+
]
1384+
};
1385+
err.multipart_suggestion_verbose(
1386+
sugg_msg,
1387+
suggestions,
13601388
Applicability::MaybeIncorrect,
13611389
);
13621390
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
3+
fn foo(x: &str) -> bool {
4+
x.starts_with(&("hi".to_string() + " you"))
5+
//~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
6+
}
7+
8+
fn foo2(x: &str) -> bool {
9+
x.starts_with(&"hi".to_string())
10+
//~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
11+
}
12+
13+
fn main() {
14+
foo("hi you");
15+
foo2("hi");
16+
}

tests/ui/suggestions/issue-104961.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
3+
fn foo(x: &str) -> bool {
4+
x.starts_with("hi".to_string() + " you")
5+
//~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
6+
}
7+
8+
fn foo2(x: &str) -> bool {
9+
x.starts_with("hi".to_string())
10+
//~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
11+
}
12+
13+
fn main() {
14+
foo("hi you");
15+
foo2("hi");
16+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
2+
--> $DIR/issue-104961.rs:4:19
3+
|
4+
LL | x.starts_with("hi".to_string() + " you")
5+
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= note: the trait bound `String: Pattern<'_>` is not satisfied
10+
= note: required for `String` to implement `Pattern<'_>`
11+
note: required by a bound in `core::str::<impl str>::starts_with`
12+
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
13+
help: consider borrowing here
14+
|
15+
LL | x.starts_with(&("hi".to_string() + " you"))
16+
| ++ +
17+
18+
error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
19+
--> $DIR/issue-104961.rs:9:19
20+
|
21+
LL | x.starts_with("hi".to_string())
22+
| ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
23+
| |
24+
| required by a bound introduced by this call
25+
|
26+
= note: the trait bound `String: Pattern<'_>` is not satisfied
27+
= note: required for `String` to implement `Pattern<'_>`
28+
note: required by a bound in `core::str::<impl str>::starts_with`
29+
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
30+
help: consider borrowing here
31+
|
32+
LL | x.starts_with(&"hi".to_string())
33+
| +
34+
35+
error: aborting due to 2 previous errors
36+
37+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)