From 8121d2e0576e74b23f0019e857b1088197ef8c04 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 15 Jun 2020 00:58:37 +0100 Subject: [PATCH] Fix up autoderef when performing mutable auto borrow --- src/librustc_typeck/check/method/confirm.rs | 5 ----- src/librustc_typeck/check/mod.rs | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 867dacede6e..c0f1f356ef3 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -119,11 +119,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // Create the final `MethodCallee`. let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig }; - - if let Some(hir::Mutability::Mut) = pick.autoref { - self.convert_place_derefs_to_mutable(self.self_expr); - } - ConfirmResult { callee, illegal_sized_bound } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1e4085f0267..82523f843ae 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3183,6 +3183,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } + let autoborrow_mut = adj.iter().any(|adj| { + matches!(adj, &Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })), + .. + }) + }); + match self.tables.borrow_mut().adjustments_mut().entry(expr.hir_id) { Entry::Vacant(entry) => { entry.insert(adj); @@ -3212,6 +3219,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *entry.get_mut() = adj; } } + + // When there is an auto mutable borrow, it is equivalent to `&mut expr`, + // thus `expr` is ought to be typechecked with needs = [`Needs::MutPlace`]. + // However in many cases it might not be checked this way originally, e.g. + // the receiver of a method call. We need to fix them up. + if autoborrow_mut { + self.convert_place_derefs_to_mutable(expr); + } } /// Basically whenever we are converting from a type scheme into