1
Fork 0

Auto merge of #112476 - chenyukang:yukang-fix-109991, r=compiler-errors

Do not emit coerce_suggestions for expr from destructuring assignment desugaring

Fixes #109991
This commit is contained in:
bors 2023-06-25 04:45:52 +00:00
commit 3c5d71a99d
4 changed files with 139 additions and 19 deletions

View file

@ -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())
}
}
(