Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not emit coerce_suggestions for expr from destructuring assignment desugaring #112476

Merged
merged 1 commit into from
Jun 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 40 additions & 14 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

self.annotate_expected_due_to_let_ty(err, expr, error);

if self.is_destruct_assignment_desugaring(expr) {
return;
}
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
self.note_type_is_not_clone(err, expected, expr_ty, expr);
self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty);
Expand Down Expand Up @@ -1253,6 +1257,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

// Returns whether the given expression is a destruct assignment desugaring.
// For example, `(a, b) = (1, &2);`
// Here we try to find the pattern binding of the expression,
// `default_binding_modes` is false only for destruct assignment desugaring.
pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
if let hir::ExprKind::Path(hir::QPath::Resolved(
_,
hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
)) = expr.kind
{
let bind = self.tcx.hir().find(*bind_hir_id);
let parent = self.tcx.hir().find(self.tcx.hir().parent_id(*bind_hir_id));
if let Some(hir::Node::Pat(hir::Pat { kind: hir::PatKind::Binding(_, _hir_id, _, _), .. })) = bind &&
let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent {
return true;
}
}
return false;
}

/// This function is used to determine potential "simple" improvements or users' errors and
/// provide them useful help. For example:
///
Expand Down Expand Up @@ -1443,6 +1467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_,
&ty::Ref(_, checked, _),
) if self.can_sub(self.param_env, checked, expected) => {
let make_sugg = |start: Span, end: BytePos| {
// skip `(` for tuples such as `(c) = (&123)`.
// make sure we won't suggest like `(c) = 123)` which is incorrect.
let sp = sm.span_extend_while(start.shrink_to_lo(), |c| c == '(' || c.is_whitespace())
.map_or(start, |s| s.shrink_to_hi());
Some((
vec![(sp.with_hi(end), String::new())],
"consider removing the borrow".to_string(),
Applicability::MachineApplicable,
true,
true,
))
};

// We have `&T`, check if what was expected was `T`. If so,
// we may want to suggest removing a `&`.
if sm.is_imported(expr.span) {
Expand All @@ -1456,24 +1494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.find(|&s| sp.contains(s))
&& sm.is_span_accessible(call_span)
{
return Some((
vec![(sp.with_hi(call_span.lo()), String::new())],
"consider removing the borrow".to_string(),
Applicability::MachineApplicable,
true,
true,
));
return make_sugg(sp, call_span.lo())
}
return None;
}
if sp.contains(expr.span) && sm.is_span_accessible(expr.span) {
return Some((
vec![(sp.with_hi(expr.span.lo()), String::new())],
"consider removing the borrow".to_string(),
Applicability::MachineApplicable,
true,
true,
));
return make_sugg(sp, expr.span.lo())
}
}
(
Expand Down
5 changes: 0 additions & 5 deletions src/tools/clippy/tests/ui/crashes/ice-6250.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ LL | for reference in vec![1, 2, 3] {
...
LL | Some(reference) = cache.data.get(key) {
| ^^^^^^^^^ expected integer, found `&i32`
|
help: consider dereferencing the borrow
|
LL | Some(*reference) = cache.data.get(key) {
| +

error[E0308]: mismatched types
--> $DIR/ice-6250.rs:12:9
Expand Down
27 changes: 27 additions & 0 deletions tests/ui/suggestions/issue-109991.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
struct S {
a: usize,
b: usize,
}

fn main() {
let a: usize;
let b: usize;
let c: usize;

(c) = (&123); //~ ERROR mismatched types
(a, b) = (123, &mut 123); //~ ERROR mismatched types

let x: String;
(x,) = (1,); //~ ERROR mismatched types

let x: i32;
[x] = [&1]; //~ ERROR mismatched types

let x: &i32;
[x] = [1]; //~ ERROR mismatched types

let x = (1, &mut 2);
(a, b) = x; //~ ERROR mismatched types

S { a, b } = S { a: 1, b: &mut 2 }; //~ ERROR mismatched types
}
72 changes: 72 additions & 0 deletions tests/ui/suggestions/issue-109991.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
error[E0308]: mismatched types
--> $DIR/issue-109991.rs:11:11
|
LL | let c: usize;
| ----- expected due to this type
LL |
LL | (c) = (&123);
| ^^^^^^ expected `usize`, found `&{integer}`
|
help: consider removing the borrow
|
LL - (c) = (&123);
LL + (c) = (123);
|

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:12:9
|
LL | let b: usize;
| ----- expected due to this type
...
LL | (a, b) = (123, &mut 123);
| ^ expected `usize`, found `&mut {integer}`

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:15:6
|
LL | let x: String;
| ------ expected due to this type
LL | (x,) = (1,);
| ^ expected `String`, found integer

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:18:6
|
LL | let x: i32;
| --- expected due to this type
LL | [x] = [&1];
| ^ expected `i32`, found `&{integer}`

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:21:6
|
LL | let x: &i32;
| ---- expected due to this type
LL | [x] = [1];
| ^ expected `&i32`, found integer

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:24:9
|
LL | let b: usize;
| ----- expected due to this type
...
LL | (a, b) = x;
| ^ expected `usize`, found `&mut {integer}`

error[E0308]: mismatched types
--> $DIR/issue-109991.rs:26:31
|
LL | S { a, b } = S { a: 1, b: &mut 2 };
| ^^^^^^ expected `usize`, found `&mut {integer}`
|
help: consider removing the borrow
|
LL - S { a, b } = S { a: 1, b: &mut 2 };
LL + S { a, b } = S { a: 1, b: 2 };
|

error: aborting due to 7 previous errors

For more information about this error, try `rustc --explain E0308`.