From 33f73c2e939afb9c71555735acef2ee20e4f10bd Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 6 Jun 2023 02:48:57 +0800 Subject: [PATCH] Do not offer any of the suggestions in emit_coerce_suggestions for expr from destructuring assignment desugaring --- compiler/rustc_hir_typeck/src/demand.rs | 54 ++++++++++---- .../clippy/tests/ui/crashes/ice-6250.stderr | 5 -- tests/ui/suggestions/issue-109991.rs | 27 +++++++ tests/ui/suggestions/issue-109991.stderr | 72 +++++++++++++++++++ 4 files changed, 139 insertions(+), 19 deletions(-) create mode 100644 tests/ui/suggestions/issue-109991.rs create mode 100644 tests/ui/suggestions/issue-109991.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9ce03060e0f..47f3c6b8407 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -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); @@ -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: /// @@ -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) { @@ -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()) } } ( diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 4506d1550bd..db34e6bfa7b 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -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 diff --git a/tests/ui/suggestions/issue-109991.rs b/tests/ui/suggestions/issue-109991.rs new file mode 100644 index 00000000000..918451cb8ee --- /dev/null +++ b/tests/ui/suggestions/issue-109991.rs @@ -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 +} diff --git a/tests/ui/suggestions/issue-109991.stderr b/tests/ui/suggestions/issue-109991.stderr new file mode 100644 index 00000000000..bd21e4de648 --- /dev/null +++ b/tests/ui/suggestions/issue-109991.stderr @@ -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`.