From 55a1e58441c66b21b4c72b30fdc8dcb9612020b0 Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 27 Mar 2023 10:38:30 +0000 Subject: [PATCH 1/3] add DerefMutArg to thir --- compiler/rustc_middle/src/thir.rs | 5 +++++ compiler/rustc_middle/src/thir/visit.rs | 1 + compiler/rustc_mir_build/src/build/expr/as_place.rs | 7 +++++-- compiler/rustc_mir_build/src/build/expr/as_rvalue.rs | 1 + compiler/rustc_mir_build/src/build/expr/category.rs | 3 ++- compiler/rustc_mir_build/src/check_unsafety.rs | 1 + compiler/rustc_mir_build/src/thir/print.rs | 6 ++++++ compiler/rustc_ty_utils/src/consts.rs | 9 ++++++--- 8 files changed, 27 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 82a7cf7851734..93ba9c0dee22e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -484,6 +484,11 @@ pub enum ExprKind<'tcx> { Yield { value: ExprId, }, + /// The argument to a `Call` of `DerefMut::deref_mut`. This is used to allow us to + /// adjust the `Mutability` of local variables that are deref'd. + DerefMutArg { + arg: ExprId, + }, } /// Represents the association of a field identifier and an expression. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 79a0e75aa7c78..1aadd294bab1b 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -57,6 +57,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp } } Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), + DerefMutArg { arg } => visitor.visit_expr(&visitor.thir()[arg]), Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { visitor.visit_expr(&visitor.thir()[lhs]); visitor.visit_expr(&visitor.thir()[rhs]); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index fb775766c6541..f03c20f155bce 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -408,8 +408,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, ) -> BlockAnd> { - debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability); - let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); @@ -437,6 +435,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); block.and(place_builder.deref()) } + ExprKind::DerefMutArg { .. } => { + bug!("encountered ExprKind::DerefMutArg in `expr_as_place`") + } ExprKind::Index { lhs, index } => this.lower_index_expression( block, &this.thir[lhs], @@ -454,9 +455,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::VarRef { id } => { let place_builder = if this.is_bound_var_in_guard(id) { let index = this.var_local_id(id, RefWithinGuard); + let local_decl = &mut this.local_decls[index]; PlaceBuilder::from(index).deref() } else { let index = this.var_local_id(id, OutsideGuard); + let local_decl = &mut this.local_decls[index]; PlaceBuilder::from(index) }; block.and(place_builder) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index baa12ec11c321..3f8e453c921a6 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -528,6 +528,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); block.and(Rvalue::Use(operand)) } + ExprKind::DerefMutArg { .. } => bug!("encountered DerefMutArg as Rvalue"), } } diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index d33401f07645e..e374140a610cd 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -54,7 +54,8 @@ impl Category { | ExprKind::AddressOf { .. } | ExprKind::Yield { .. } | ExprKind::Call { .. } - | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)), + | ExprKind::InlineAsm { .. } + | ExprKind::DerefMutArg { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } | ExprKind::Tuple { .. } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 03a7f2d70faeb..6db1e78c2ea12 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -324,6 +324,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::If { .. } | ExprKind::InlineAsm { .. } | ExprKind::LogicalOp { .. } + | ExprKind::DerefMutArg { .. } | ExprKind::Use { .. } => { // We don't need to save the old value and restore it // because all the place expressions can't have more diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 8028227aafd2a..c257e77e8ce1a 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -528,6 +528,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl); } + DerefMutArg { arg } => { + print_indented!(self, "DerefMutArg {", depth_lvl); + print_indented!(self, "arg:", depth_lvl + 1); + self.print_expr(*arg, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } } } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index b67607a4db63e..0987c8247a0f3 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -194,9 +194,11 @@ fn recurse_build<'tcx>( } } // FIXME(generic_const_exprs): We may want to support these. - ExprKind::AddressOf { .. } | ExprKind::Deref { .. } => maybe_supported_error( - GenericConstantTooComplexSub::AddressAndDerefNotSupported(node.span), - )?, + ExprKind::AddressOf { .. } | ExprKind::Deref { .. } | ExprKind::DerefMutArg { .. } => { + maybe_supported_error(GenericConstantTooComplexSub::AddressAndDerefNotSupported( + node.span, + ))? + } ExprKind::Repeat { .. } | ExprKind::Array { .. } => { maybe_supported_error(GenericConstantTooComplexSub::ArrayNotSupported(node.span))? } @@ -314,6 +316,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::If { .. } | thir::ExprKind::Call { .. } | thir::ExprKind::Deref { .. } + | thir::ExprKind::DerefMutArg { .. } | thir::ExprKind::Binary { .. } | thir::ExprKind::LogicalOp { .. } | thir::ExprKind::Unary { .. } From 546f101a88c8c71609a4590f8761d838bb59e3e4 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 29 Mar 2023 11:06:13 +0000 Subject: [PATCH 2/3] use new BorrowKind variant on DerefMut::deref_mut receiver --- compiler/rustc_borrowck/src/borrow_set.rs | 1 + .../src/diagnostics/conflict_errors.rs | 19 ++-- .../rustc_borrowck/src/diagnostics/mod.rs | 9 +- compiler/rustc_borrowck/src/invalidation.rs | 9 +- compiler/rustc_borrowck/src/lib.rs | 19 +++- .../src/transform/check_consts/check.rs | 4 +- .../src/transform/check_consts/resolver.rs | 2 +- .../src/transform/promote_consts.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 8 +- compiler/rustc_middle/src/mir/syntax.rs | 17 ++++ compiler/rustc_middle/src/mir/tcx.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 2 +- .../src/build/expr/as_place.rs | 2 - .../rustc_mir_build/src/build/expr/into.rs | 96 ++++++++++++++++++- .../rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 78 +++++++++++++-- 16 files changed, 235 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index fa0552e012de1..1b129c616f21f 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -75,6 +75,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { mir::BorrowKind::Shallow => "shallow ", mir::BorrowKind::Unique => "uniq ", mir::BorrowKind::Mut { .. } => "mut ", + mir::BorrowKind::DerefMut => "deref mut", }; write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 75a3dd0c0f3d6..2f5b4e6874b5a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -919,7 +919,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME: supply non-"" `opt_via` when appropriate let first_borrow_desc; let mut err = match (gen_borrow_kind, issued_borrow.kind) { - (BorrowKind::Shared, BorrowKind::Mut { .. }) => { + (BorrowKind::Shared, BorrowKind::Mut { .. } | BorrowKind::DerefMut) => { first_borrow_desc = "mutable "; self.cannot_reborrow_already_borrowed( span, @@ -933,7 +933,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ) } - (BorrowKind::Mut { .. }, BorrowKind::Shared) => { + (BorrowKind::Mut { .. } | BorrowKind::DerefMut, BorrowKind::Shared) => { first_borrow_desc = "immutable "; let mut err = self.cannot_reborrow_already_borrowed( span, @@ -954,7 +954,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err } - (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => { + ( + BorrowKind::Mut { .. } | BorrowKind::DerefMut, + BorrowKind::Mut { .. } | BorrowKind::DerefMut, + ) => { first_borrow_desc = "first "; let mut err = self.cannot_mutably_borrow_multiply( span, @@ -977,7 +980,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None) } - (BorrowKind::Mut { .. } | BorrowKind::Unique, BorrowKind::Shallow) => { + ( + BorrowKind::Mut { .. } | BorrowKind::Unique | BorrowKind::DerefMut, + BorrowKind::Shallow, + ) => { if let Some(immutable_section_description) = self.classify_immutable_section(issued_borrow.assigned_place) { @@ -1044,7 +1050,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) } - (BorrowKind::Mut { .. }, BorrowKind::Unique) => { + (BorrowKind::Mut { .. } | BorrowKind::DerefMut, BorrowKind::Unique) => { first_borrow_desc = "first "; self.cannot_reborrow_already_uniquely_borrowed( span, @@ -1065,7 +1071,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { BorrowKind::Mut { .. } | BorrowKind::Unique | BorrowKind::Shared - | BorrowKind::Shallow, + | BorrowKind::Shallow + | BorrowKind::DerefMut, ) => unreachable!(), }; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 7bd4331c5ed92..25191a9239802 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -645,17 +645,18 @@ impl UseSpans<'_> { f: impl Fn(Option, Span) -> crate::session_diagnostics::CaptureVarCause, ) { use crate::session_diagnostics::CaptureVarKind::*; + use rustc_middle::mir::BorrowKind; + if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { if capture_kind_span != path_span { err.subdiagnostic(match kind { Some(kd) => match kd { - rustc_middle::mir::BorrowKind::Shared - | rustc_middle::mir::BorrowKind::Shallow - | rustc_middle::mir::BorrowKind::Unique => { + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => { Immute { kind_span: capture_kind_span } } - rustc_middle::mir::BorrowKind::Mut { .. } => { + rustc_middle::mir::BorrowKind::Mut { .. } + | rustc_middle::mir::BorrowKind::DerefMut => { Mut { kind_span: capture_kind_span } } }, diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index a71c416328611..f707b87c03f03 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -253,7 +253,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), - BorrowKind::Unique | BorrowKind::Mut { .. } => { + BorrowKind::Unique | BorrowKind::Mut { .. } | BorrowKind::DerefMut => { let wk = WriteKind::MutableBorrow(bk); if allow_two_phase_borrow(bk) { (Deep, Reservation(wk)) @@ -381,7 +381,10 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // Reads don't invalidate shared or shallow borrows } - (Read(_), BorrowKind::Unique | BorrowKind::Mut { .. }) => { + ( + Read(_), + BorrowKind::Unique | BorrowKind::Mut { .. } | BorrowKind::DerefMut, + ) => { // Reading from mere reservations of mutable-borrows is OK. if !is_active(&this.dominators, borrow, location) { // If the borrow isn't active yet, reads don't invalidate it @@ -422,7 +425,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::DerefMut => false, BorrowKind::Unique | BorrowKind::Mut { .. } => true, }); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 1d4d1406239d9..f6fd0b631a66c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1176,6 +1176,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } Control::Break } + (_, BorrowKind::DerefMut) => bug!( + "should never encounter BorrowKind::DerefMut when checking for place accesses" + ), }, ); @@ -1201,6 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + #[instrument(skip(self, flow_state), level = "debug")] fn consume_rvalue( &mut self, location: Location, @@ -1214,7 +1218,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), - BorrowKind::Unique | BorrowKind::Mut { .. } => { + BorrowKind::Unique | BorrowKind::Mut { .. } | BorrowKind::DerefMut => { let wk = WriteKind::MutableBorrow(bk); if allow_two_phase_borrow(bk) { (Deep, Reservation(wk)) @@ -1584,7 +1588,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::DerefMut => false, BorrowKind::Unique | BorrowKind::Mut { .. } => true, }); @@ -1962,6 +1966,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Checks the permissions for the given place and read or write kind /// /// Returns `true` if an error is reported. + #[instrument(skip(self, flow_state), level = "debug")] fn check_access_permissions( &mut self, (place, span): (Place<'tcx>, Span), @@ -1979,14 +1984,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let the_place_err; match kind { + Reservation(WriteKind::MutableBorrow(BorrowKind::DerefMut)) + | Read(ReadKind::Borrow(BorrowKind::DerefMut)) => { + bug!( + "should never encounter BorrowKind::DerefMut with Reservation or Read when checking access permissions" + ); + } Reservation(WriteKind::MutableBorrow( borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }), )) | Write(WriteKind::MutableBorrow( - borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }), + borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. } | BorrowKind::DerefMut), )) => { let is_local_mutation_allowed = match borrow_kind { - BorrowKind::Unique => LocalMutationIsAllowed::Yes, + BorrowKind::Unique | BorrowKind::DerefMut => LocalMutationIsAllowed::Yes, BorrowKind::Mut { .. } => is_local_mutation_allowed, BorrowKind::Shared | BorrowKind::Shallow => unreachable!(), }; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d6110a050f2dc..bd5e3adc4d019 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -415,7 +415,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { BorrowKind::Unique => { PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) } - BorrowKind::Mut { .. } => { + BorrowKind::Mut { .. } | BorrowKind::DerefMut => { PlaceContext::MutatingUse(MutatingUseContext::Borrow) } }; @@ -459,7 +459,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique), place) => { + Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique | BorrowKind::DerefMut), place) => { let ty = place.ty(self.body, self.tcx).ty; let is_allowed = match ty.kind() { // Inside a `static mut`, `&mut [...]` is allowed. diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 78c74e1892dc5..10468bed53308 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -102,7 +102,7 @@ where fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool { match kind { - mir::BorrowKind::Mut { .. } => true, + mir::BorrowKind::Mut { .. } | mir::BorrowKind::DerefMut => true, mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => { self.shared_borrow_allows_mutation(place) } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 6774e5a583764..182fb9b78cda7 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -466,7 +466,7 @@ impl<'tcx> Validator<'_, 'tcx> { } } - BorrowKind::Mut { .. } => { + BorrowKind::Mut { .. } | BorrowKind::DerefMut => { let ty = place.ty(self.body, self.tcx).ty; // In theory, any zero-sized value could be borrowed diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 44fd8478be9b5..ce9f6709b6c0b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1993,7 +1993,10 @@ impl<'tcx> Rvalue<'tcx> { impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { - BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, + BorrowKind::Shared + | BorrowKind::Shallow + | BorrowKind::Unique + | BorrowKind::DerefMut => false, BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, } } @@ -2002,7 +2005,7 @@ impl BorrowKind { pub fn describe_mutability(&self) -> &str { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable", - BorrowKind::Mut { .. } => "mutable", + BorrowKind::Mut { .. } | BorrowKind::DerefMut => "mutable", } } } @@ -2036,6 +2039,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { Ref(region, borrow_kind, ref place) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", + BorrowKind::DerefMut => "deref mut ", BorrowKind::Shallow => "shallow ", BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ", }; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index cc35e6106e294..24a31a6df9866 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -228,6 +228,23 @@ pub enum BorrowKind { /// (i.e., `adjustment::Adjust::Borrow`). allow_two_phase_borrow: bool, }, + + /// Corresponds to the borrow of the receiver in `DerefMut::deref_mut`. We don't want + /// to require the `mut` keyword for deref assignments on variables that implement + /// `DerefMut` to be more consistent with how we handle `&mut` in that case. More specifically + /// we want to allow the following to compile: + /// + /// ```ignore (rust) + /// fn bar_mut(y: RefMut<'_, u32>) { + /// *y = 3; + /// } + /// ``` + /// + /// given that the `mut` on mutable references is implicit too. + /// + /// `BorrowKind::DerefMut` is necessary in order to allow the borrow checker to let + /// this pass without `y` being `mut`. + DerefMut, } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 0092401470f56..8f18a1bb91e4e 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -257,7 +257,7 @@ impl<'tcx> BinOp { impl BorrowKind { pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - BorrowKind::Mut { .. } => hir::Mutability::Mut, + BorrowKind::Mut { .. } | BorrowKind::DerefMut => hir::Mutability::Mut, BorrowKind::Shared => hir::Mutability::Not, // We have no type corresponding to a unique imm borrow, so diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 7aa446ae966c6..167ac26c231f2 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -643,7 +643,7 @@ macro_rules! make_mir_visitor { BorrowKind::Unique => PlaceContext::NonMutatingUse( NonMutatingUseContext::UniqueBorrow ), - BorrowKind::Mut { .. } => + BorrowKind::Mut { .. } | BorrowKind::DerefMut => PlaceContext::MutatingUse(MutatingUseContext::Borrow), }; self.visit_place(path, ctx, location); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index f03c20f155bce..75ff5367a1ec8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -455,11 +455,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::VarRef { id } => { let place_builder = if this.is_bound_var_in_guard(id) { let index = this.var_local_id(id, RefWithinGuard); - let local_decl = &mut this.local_decls[index]; PlaceBuilder::from(index).deref() } else { let index = this.var_local_id(id, OutsideGuard); - let local_decl = &mut this.local_decls[index]; PlaceBuilder::from(index) }; block.and(place_builder) diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 8efaba1f602e0..7fd7de925070b 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -1,6 +1,7 @@ //! See docs in build/expr/mod.rs use crate::build::expr::category::{Category, RvalueFunc}; +use crate::build::ForGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary}; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxHashMap; @@ -506,8 +507,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Create a "fake" temporary variable so that we check that the // value is Sized. Usually, this is caught in type checking, but // in the case of box expr there is no such check. + let local_decl = LocalDecl::new(expr.ty, expr.span); if !destination.projection.is_empty() { - this.local_decls.push(LocalDecl::new(expr.ty, expr.span)); + this.local_decls.push(local_decl); } let place = unpack!(block = this.as_place(block, expr)); @@ -571,6 +573,46 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } + ExprKind::DerefMutArg { arg } => { + let thir_arg = &this.thir[arg]; + debug!("thir_arg: {:#?}", thir_arg); + + // we have to manually unwrap the scope here instead of letting `expr_into_dest` handle + // the scope. + if let ExprKind::Scope { region_scope, lint_level, value } = thir_arg.kind { + let source_info = this.source_info(expr.span); + let region_scope = (region_scope, source_info); + + ensure_sufficient_stack(|| { + this.in_scope(region_scope, lint_level, |this| { + let expr = &this.thir[value]; + let ExprKind::Borrow { borrow_kind, arg} = expr.kind else { + bug!("expected ExprKind::Borrow, found: {:?}", expr.kind); + }; + + let arg = &this.thir[arg]; + let borrow; + (block, borrow) = + this.create_deref_mut_receiver_ref(block, arg, borrow_kind); + this.cfg.push_assign(block, source_info, destination, borrow); + + block.unit() + }) + }) + } else { + let expr = thir_arg; + let ExprKind::Borrow { borrow_kind, arg} = expr.kind else { + bug!("expected ExprKind::Borrow, found: {:?}", expr.kind); + }; + + let arg = &this.thir[arg]; + let borrow; + (block, borrow) = this.create_deref_mut_receiver_ref(block, arg, borrow_kind); + this.cfg.push_assign(block, source_info, destination, borrow); + + block.unit() + } + } }; if !expr_is_block_or_scope { @@ -581,6 +623,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block_and } + /// Adjusts `borrow_kind` from `BorrowKind::Mut` to `BorrowKind::DerefMut` if `expr` corresponds + /// to a local variable that isn't `mut`. This is necessary to allow the following to compile: + /// + /// ```ignore (rust) + /// fn bar(y: RefMut<'_, u32>) { + /// *y = 3; + /// } + /// ``` + /// + /// The borrow checker requires variables to be `mut` if it encounters `BorrowKind::Mut`. + fn adjust_borrow_kind_for_deref_mut( + &mut self, + expr: &Expr<'tcx>, + borrow_kind: BorrowKind, + ) -> BorrowKind { + if let ExprKind::VarRef { id } = expr.kind { + if let BorrowKind::Mut { .. } = borrow_kind { + let index = self.var_local_id(id, ForGuard::OutsideGuard); + let local_decl = &mut self.local_decls[index]; + + if local_decl.mutability != Mutability::Mut { + return BorrowKind::DerefMut; + } + } + }; + + borrow_kind + } + + fn create_deref_mut_receiver_ref( + &mut self, + mut block: BasicBlock, + arg: &Expr<'tcx>, + borrow_kind: BorrowKind, + ) -> (BasicBlock, Rvalue<'tcx>) { + let borrow_kind = self.adjust_borrow_kind_for_deref_mut(arg, borrow_kind); + + // We don't do this in `as_rvalue` because we use `as_place` + // for borrow expressions, so we cannot create an `RValue` that + // remains valid across user code. `as_rvalue` is usually called + // by this method anyway, so this shouldn't cause too many + // unnecessary temporaries. + let arg_place = match borrow_kind { + BorrowKind::Shared => { + unpack!(block = self.as_read_only_place(block, arg)) + } + _ => unpack!(block = self.as_place(block, arg)), + }; + + (block, Rvalue::Ref(self.tcx.lifetimes.re_erased, borrow_kind, arg_place)) + } + fn is_let(&self, expr: ExprId) -> bool { match self.thir[expr].kind { ExprKind::Let { .. } => true, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 6db1e78c2ea12..dedb3e2a319ca 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -259,7 +259,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } - BorrowKind::Mut { .. } => { + BorrowKind::Mut { .. } | BorrowKind::DerefMut => { self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); } } @@ -452,7 +452,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) } - BorrowKind::Mut { .. } => { + BorrowKind::Mut { .. } | BorrowKind::DerefMut => { self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField) } BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {} diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 8e2e92e6f6a94..7852069e530b7 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -154,7 +154,14 @@ impl<'tcx> Cx<'tcx> { let expr = Box::new([self.thir.exprs.push(expr)]); - self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span) + self.overloaded_place( + hir_expr, + adjustment.target, + Some(call), + expr, + deref.span, + OverloadedPlaceKind::Deref, + ) } Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), @@ -467,7 +474,14 @@ impl<'tcx> Cx<'tcx> { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr(lhs); let index = self.mirror_expr(index); - self.overloaded_place(expr, expr_ty, None, Box::new([lhs, index]), expr.span) + self.overloaded_place( + expr, + expr_ty, + None, + Box::new([lhs, index]), + expr.span, + OverloadedPlaceKind::Index, + ) } else { ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) } } @@ -476,7 +490,14 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr(arg); - self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span) + self.overloaded_place( + expr, + expr_ty, + None, + Box::new([arg]), + expr.span, + OverloadedPlaceKind::Deref, + ) } else { ExprKind::Deref { arg: self.mirror_expr(arg) } } @@ -987,6 +1008,7 @@ impl<'tcx> Cx<'tcx> { overloaded_callee: Option>, args: Box<[ExprId]>, span: Span, + kind: OverloadedPlaceKind, ) -> ExprKind<'tcx> { // For an overloaded *x or x[y] expression of type T, the method // call returns an &T and we must add the deref so that the types @@ -1007,12 +1029,44 @@ impl<'tcx> Cx<'tcx> { let fun = self.method_callee(expr, span, overloaded_callee); let fun = self.thir.exprs.push(fun); let fun_ty = self.thir[fun].ty; - let ref_expr = self.thir.exprs.push(Expr { - temp_lifetime, - ty: ref_ty, - span, - kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span }, - }); + debug!(?fun_ty); + + let ref_expr = if let OverloadedPlaceKind::Deref = kind { + assert_eq!(args.len(), 1); + let Expr { temp_lifetime: arg_temp_lifetime, ty: arg_ty, span: arg_span, kind } = + &self.thir[args[0]]; + + debug!(?kind); + + let arg = self.thir.exprs.push(Expr { + temp_lifetime: *arg_temp_lifetime, + ty: *arg_ty, + span: *arg_span, + kind: ExprKind::DerefMutArg { arg: args[0] }, + }); + + self.thir.exprs.push(Expr { + temp_lifetime, + ty: ref_ty, + span, + kind: ExprKind::Call { + ty: fun_ty, + fun, + args: Box::new([arg]), + from_hir_call: false, + fn_span: span, + }, + }) + } else { + self.thir.exprs.push(Expr { + temp_lifetime, + ty: ref_ty, + span, + kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span }, + }) + }; + + debug!(?ref_expr); // construct and return a deref wrapper `*foo()` ExprKind::Deref { arg: ref_expr } @@ -1163,3 +1217,9 @@ fn bin_op(op: hir::BinOpKind) -> BinOp { _ => bug!("no equivalent for ast binop {:?}", op), } } + +#[derive(Copy, Clone, Debug)] +enum OverloadedPlaceKind { + Index, + Deref, +} From 0f7d5ca9b522ae49818deb2354897f5637e3f0c8 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 31 Mar 2023 15:18:31 +0000 Subject: [PATCH 3/3] add test, bless tests --- tests/ui/async-await/issues/issue-61187.rs | 3 +- .../ui/async-await/issues/issue-61187.stderr | 14 ------ tests/ui/borrowck/deref-mut.rs | 31 +++++++++++++ tests/ui/borrowck/deref-mut.stderr | 36 +++++++++++++++ ...rrowck-borrow-overloaded-auto-deref-mut.rs | 12 ++--- ...ck-borrow-overloaded-auto-deref-mut.stderr | 46 +------------------ .../borrowck-borrow-overloaded-deref-mut.rs | 4 +- ...orrowck-borrow-overloaded-deref-mut.stderr | 24 +--------- 8 files changed, 79 insertions(+), 91 deletions(-) delete mode 100644 tests/ui/async-await/issues/issue-61187.stderr create mode 100644 tests/ui/borrowck/deref-mut.rs create mode 100644 tests/ui/borrowck/deref-mut.stderr diff --git a/tests/ui/async-await/issues/issue-61187.rs b/tests/ui/async-await/issues/issue-61187.rs index 8585a42511104..16e13e952237b 100644 --- a/tests/ui/async-await/issues/issue-61187.rs +++ b/tests/ui/async-await/issues/issue-61187.rs @@ -1,7 +1,8 @@ +// build-pass // edition:2018 fn main() {} async fn response(data: Vec) { - data.reverse(); //~ ERROR E0596 + data.reverse(); } diff --git a/tests/ui/async-await/issues/issue-61187.stderr b/tests/ui/async-await/issues/issue-61187.stderr deleted file mode 100644 index e58f74546899b..0000000000000 --- a/tests/ui/async-await/issues/issue-61187.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable - --> $DIR/issue-61187.rs:6:5 - | -LL | data.reverse(); - | ^^^^^^^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | async fn response(mut data: Vec) { - | +++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/deref-mut.rs b/tests/ui/borrowck/deref-mut.rs new file mode 100644 index 0000000000000..ce03e987c0f85 --- /dev/null +++ b/tests/ui/borrowck/deref-mut.rs @@ -0,0 +1,31 @@ +use std::cell::RefMut; + +struct Foo { + a: u32, +} + +fn func1(y: RefMut<'_, Foo>) { + let shared_ref = &y; + *y = Foo { a: 3 }; + //~^ ERROR cannot borrow `y` as mutable because it is also borrowed as immutable + takes_shared_foo_ref(shared_ref); +} + +fn func2(y: RefMut<'_, Foo>) { + let shared_ref = &y.a; + *y = Foo { a: 3 }; + //~^ ERROR cannot borrow `y` as mutable because it is also borrowed as immutable + takes_shared_u32_ref(shared_ref); +} + +fn func3(y: RefMut<'_, Foo>) { + let shared_ref = &y.a; + y.a = 3; + //~^ ERROR cannot borrow `y` as mutable because it is also borrowed as immutable + takes_shared_u32_ref(shared_ref); +} + +fn takes_shared_foo_ref<'a>(x: &'a RefMut<'_, Foo>) {} +fn takes_shared_u32_ref<'a>(x: &'a u32) {} + +fn main() {} diff --git a/tests/ui/borrowck/deref-mut.stderr b/tests/ui/borrowck/deref-mut.stderr new file mode 100644 index 0000000000000..8f01a43c291a6 --- /dev/null +++ b/tests/ui/borrowck/deref-mut.stderr @@ -0,0 +1,36 @@ +error[E0502]: cannot borrow `y` as mutable because it is also borrowed as immutable + --> $DIR/deref-mut.rs:9:6 + | +LL | let shared_ref = &y; + | -- immutable borrow occurs here +LL | *y = Foo { a: 3 }; + | ^ mutable borrow occurs here +LL | +LL | takes_shared_foo_ref(shared_ref); + | ---------- immutable borrow later used here + +error[E0502]: cannot borrow `y` as mutable because it is also borrowed as immutable + --> $DIR/deref-mut.rs:16:6 + | +LL | let shared_ref = &y.a; + | - immutable borrow occurs here +LL | *y = Foo { a: 3 }; + | ^ mutable borrow occurs here +LL | +LL | takes_shared_u32_ref(shared_ref); + | ---------- immutable borrow later used here + +error[E0502]: cannot borrow `y` as mutable because it is also borrowed as immutable + --> $DIR/deref-mut.rs:23:5 + | +LL | let shared_ref = &y.a; + | - immutable borrow occurs here +LL | y.a = 3; + | ^ mutable borrow occurs here +LL | +LL | takes_shared_u32_ref(shared_ref); + | ---------- immutable borrow later used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs index 76a1d12ea944a..5970041cb412d 100644 --- a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut}; struct Own { - value: *mut T + value: *mut T, } impl Deref for Own { @@ -23,7 +23,7 @@ impl DerefMut for Own { struct Point { x: isize, - y: isize + y: isize, } impl Point { @@ -50,7 +50,7 @@ fn deref_imm_field(x: Own) { } fn deref_mut_field1(x: Own) { - let __isize = &mut x.y; //~ ERROR cannot borrow + let __isize = &mut x.y; } fn deref_mut_field2(mut x: Own) { @@ -85,7 +85,7 @@ fn deref_extend_mut_field4<'a>(x: &'a mut Own) { } fn assign_field1<'a>(x: Own) { - x.y = 3; //~ ERROR cannot borrow + x.y = 3; } fn assign_field2<'a>(x: &'a Own) { @@ -106,7 +106,7 @@ fn deref_imm_method(x: Own) { } fn deref_mut_method1(x: Own) { - x.set(0, 0); //~ ERROR cannot borrow + x.set(0, 0); } fn deref_mut_method2(mut x: Own) { @@ -126,7 +126,7 @@ fn deref_extend_mut_method2(x: &mut Own) -> &mut isize { } fn assign_method1<'a>(x: Own) { - *x.y_mut() = 3; //~ ERROR cannot borrow + *x.y_mut() = 3; } fn assign_method2<'a>(x: &'a Own) { diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 570328fc211f9..0006189dce7a3 100644 --- a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -1,14 +1,3 @@ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24 - | -LL | let __isize = &mut x.y; - | ^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn deref_mut_field1(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10 | @@ -30,17 +19,6 @@ LL | let _y = &mut x.y; LL | use_mut(_x); | -- first borrow later used here -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5 - | -LL | x.y = 3; - | ^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn assign_field1<'a>(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5 | @@ -62,17 +40,6 @@ LL | x.y = 3; LL | use_mut(_p); | -- first borrow later used here -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5 - | -LL | x.set(0, 0); - | ^^^^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn deref_mut_method1(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 | @@ -84,17 +51,6 @@ help: consider changing this to be a mutable reference LL | fn deref_extend_mut_method1(x: &mut Own) -> &mut isize { | ~~~~~~~~~~~~~~~ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 - | -LL | *x.y_mut() = 3; - | ^^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn assign_method1<'a>(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 | @@ -106,7 +62,7 @@ help: consider changing this to be a mutable reference LL | fn assign_method2<'a>(x: &'a mut Own) { | ~~~~~~~~~~~~~~~~~~ -error: aborting due to 10 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0499, E0596. For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs index 8d43d5da430f5..0c42cf3d872e0 100644 --- a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs @@ -26,7 +26,7 @@ fn deref_imm(x: Own) { } fn deref_mut1(x: Own) { - let __isize = &mut *x; //~ ERROR cannot borrow + let __isize = &mut *x; } fn deref_mut2(mut x: Own) { @@ -46,7 +46,7 @@ fn deref_extend_mut2<'a>(x: &'a mut Own) -> &'a mut isize { } fn assign1<'a>(x: Own) { - *x = 3; //~ ERROR cannot borrow + *x = 3; } fn assign2<'a>(x: &'a Own) { diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 3fed7b3f4dcf3..d4e0c3c039db4 100644 --- a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -1,14 +1,3 @@ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25 - | -LL | let __isize = &mut *x; - | ^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn deref_mut1(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11 | @@ -20,17 +9,6 @@ help: consider changing this to be a mutable reference LL | fn deref_extend_mut1<'a>(x: &'a mut Own) -> &'a mut isize { | ~~~~~~~~~~~~~~~~~~ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6 - | -LL | *x = 3; - | ^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | fn assign1<'a>(mut x: Own) { - | +++ - error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6 | @@ -42,6 +20,6 @@ help: consider changing this to be a mutable reference LL | fn assign2<'a>(x: &'a mut Own) { | ~~~~~~~~~~~~~~~~~~ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`.