Skip to content

Commit 3c5d71a

Browse files
committed
Auto merge of #112476 - chenyukang:yukang-fix-109991, r=compiler-errors
Do not emit coerce_suggestions for expr from destructuring assignment desugaring Fixes #109991
2 parents 7b9b127 + 33f73c2 commit 3c5d71a

File tree

4 files changed

+139
-19
lines changed

4 files changed

+139
-19
lines changed

Diff for: compiler/rustc_hir_typeck/src/demand.rs

+40-14
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8383
}
8484

8585
self.annotate_expected_due_to_let_ty(err, expr, error);
86+
87+
if self.is_destruct_assignment_desugaring(expr) {
88+
return;
89+
}
8690
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
8791
self.note_type_is_not_clone(err, expected, expr_ty, expr);
8892
self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty);
@@ -1253,6 +1257,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12531257
false
12541258
}
12551259

1260+
// Returns whether the given expression is a destruct assignment desugaring.
1261+
// For example, `(a, b) = (1, &2);`
1262+
// Here we try to find the pattern binding of the expression,
1263+
// `default_binding_modes` is false only for destruct assignment desugaring.
1264+
pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
1265+
if let hir::ExprKind::Path(hir::QPath::Resolved(
1266+
_,
1267+
hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
1268+
)) = expr.kind
1269+
{
1270+
let bind = self.tcx.hir().find(*bind_hir_id);
1271+
let parent = self.tcx.hir().find(self.tcx.hir().parent_id(*bind_hir_id));
1272+
if let Some(hir::Node::Pat(hir::Pat { kind: hir::PatKind::Binding(_, _hir_id, _, _), .. })) = bind &&
1273+
let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent {
1274+
return true;
1275+
}
1276+
}
1277+
return false;
1278+
}
1279+
12561280
/// This function is used to determine potential "simple" improvements or users' errors and
12571281
/// provide them useful help. For example:
12581282
///
@@ -1443,6 +1467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14431467
_,
14441468
&ty::Ref(_, checked, _),
14451469
) if self.can_sub(self.param_env, checked, expected) => {
1470+
let make_sugg = |start: Span, end: BytePos| {
1471+
// skip `(` for tuples such as `(c) = (&123)`.
1472+
// make sure we won't suggest like `(c) = 123)` which is incorrect.
1473+
let sp = sm.span_extend_while(start.shrink_to_lo(), |c| c == '(' || c.is_whitespace())
1474+
.map_or(start, |s| s.shrink_to_hi());
1475+
Some((
1476+
vec![(sp.with_hi(end), String::new())],
1477+
"consider removing the borrow".to_string(),
1478+
Applicability::MachineApplicable,
1479+
true,
1480+
true,
1481+
))
1482+
};
1483+
14461484
// We have `&T`, check if what was expected was `T`. If so,
14471485
// we may want to suggest removing a `&`.
14481486
if sm.is_imported(expr.span) {
@@ -1456,24 +1494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14561494
.find(|&s| sp.contains(s))
14571495
&& sm.is_span_accessible(call_span)
14581496
{
1459-
return Some((
1460-
vec![(sp.with_hi(call_span.lo()), String::new())],
1461-
"consider removing the borrow".to_string(),
1462-
Applicability::MachineApplicable,
1463-
true,
1464-
true,
1465-
));
1497+
return make_sugg(sp, call_span.lo())
14661498
}
14671499
return None;
14681500
}
14691501
if sp.contains(expr.span) && sm.is_span_accessible(expr.span) {
1470-
return Some((
1471-
vec![(sp.with_hi(expr.span.lo()), String::new())],
1472-
"consider removing the borrow".to_string(),
1473-
Applicability::MachineApplicable,
1474-
true,
1475-
true,
1476-
));
1502+
return make_sugg(sp, expr.span.lo())
14771503
}
14781504
}
14791505
(

Diff for: src/tools/clippy/tests/ui/crashes/ice-6250.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ LL | for reference in vec![1, 2, 3] {
1212
...
1313
LL | Some(reference) = cache.data.get(key) {
1414
| ^^^^^^^^^ expected integer, found `&i32`
15-
|
16-
help: consider dereferencing the borrow
17-
|
18-
LL | Some(*reference) = cache.data.get(key) {
19-
| +
2015

2116
error[E0308]: mismatched types
2217
--> $DIR/ice-6250.rs:12:9

Diff for: tests/ui/suggestions/issue-109991.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
struct S {
2+
a: usize,
3+
b: usize,
4+
}
5+
6+
fn main() {
7+
let a: usize;
8+
let b: usize;
9+
let c: usize;
10+
11+
(c) = (&123); //~ ERROR mismatched types
12+
(a, b) = (123, &mut 123); //~ ERROR mismatched types
13+
14+
let x: String;
15+
(x,) = (1,); //~ ERROR mismatched types
16+
17+
let x: i32;
18+
[x] = [&1]; //~ ERROR mismatched types
19+
20+
let x: &i32;
21+
[x] = [1]; //~ ERROR mismatched types
22+
23+
let x = (1, &mut 2);
24+
(a, b) = x; //~ ERROR mismatched types
25+
26+
S { a, b } = S { a: 1, b: &mut 2 }; //~ ERROR mismatched types
27+
}

Diff for: tests/ui/suggestions/issue-109991.stderr

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-109991.rs:11:11
3+
|
4+
LL | let c: usize;
5+
| ----- expected due to this type
6+
LL |
7+
LL | (c) = (&123);
8+
| ^^^^^^ expected `usize`, found `&{integer}`
9+
|
10+
help: consider removing the borrow
11+
|
12+
LL - (c) = (&123);
13+
LL + (c) = (123);
14+
|
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/issue-109991.rs:12:9
18+
|
19+
LL | let b: usize;
20+
| ----- expected due to this type
21+
...
22+
LL | (a, b) = (123, &mut 123);
23+
| ^ expected `usize`, found `&mut {integer}`
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/issue-109991.rs:15:6
27+
|
28+
LL | let x: String;
29+
| ------ expected due to this type
30+
LL | (x,) = (1,);
31+
| ^ expected `String`, found integer
32+
33+
error[E0308]: mismatched types
34+
--> $DIR/issue-109991.rs:18:6
35+
|
36+
LL | let x: i32;
37+
| --- expected due to this type
38+
LL | [x] = [&1];
39+
| ^ expected `i32`, found `&{integer}`
40+
41+
error[E0308]: mismatched types
42+
--> $DIR/issue-109991.rs:21:6
43+
|
44+
LL | let x: &i32;
45+
| ---- expected due to this type
46+
LL | [x] = [1];
47+
| ^ expected `&i32`, found integer
48+
49+
error[E0308]: mismatched types
50+
--> $DIR/issue-109991.rs:24:9
51+
|
52+
LL | let b: usize;
53+
| ----- expected due to this type
54+
...
55+
LL | (a, b) = x;
56+
| ^ expected `usize`, found `&mut {integer}`
57+
58+
error[E0308]: mismatched types
59+
--> $DIR/issue-109991.rs:26:31
60+
|
61+
LL | S { a, b } = S { a: 1, b: &mut 2 };
62+
| ^^^^^^ expected `usize`, found `&mut {integer}`
63+
|
64+
help: consider removing the borrow
65+
|
66+
LL - S { a, b } = S { a: 1, b: &mut 2 };
67+
LL + S { a, b } = S { a: 1, b: 2 };
68+
|
69+
70+
error: aborting due to 7 previous errors
71+
72+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)