From b2eed3a559e1e59900261f4a5abf11053590e9df Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Tue, 2 Feb 2021 03:13:19 +1100 Subject: [PATCH 1/4] Point out implicit deref coercions in borrow Clean up code --- .../diagnostics/conflict_errors.rs | 37 ++++++++++++++++-- src/test/ui/borrowck/issue-81365-2.rs | 30 +++++++++++++++ src/test/ui/borrowck/issue-81365-2.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-3.rs | 37 ++++++++++++++++++ src/test/ui/borrowck/issue-81365-3.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-4.rs | 38 +++++++++++++++++++ src/test/ui/borrowck/issue-81365-4.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-5.rs | 33 ++++++++++++++++ src/test/ui/borrowck/issue-81365-5.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-6.rs | 23 +++++++++++ src/test/ui/borrowck/issue-81365-6.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-7.rs | 24 ++++++++++++ src/test/ui/borrowck/issue-81365-7.stderr | 15 ++++++++ src/test/ui/borrowck/issue-81365-8.rs | 26 +++++++++++++ src/test/ui/borrowck/issue-81365.rs | 26 +++++++++++++ src/test/ui/borrowck/issue-81365.stderr | 15 ++++++++ 16 files changed, 375 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/borrowck/issue-81365-2.rs create mode 100644 src/test/ui/borrowck/issue-81365-2.stderr create mode 100644 src/test/ui/borrowck/issue-81365-3.rs create mode 100644 src/test/ui/borrowck/issue-81365-3.stderr create mode 100644 src/test/ui/borrowck/issue-81365-4.rs create mode 100644 src/test/ui/borrowck/issue-81365-4.stderr create mode 100644 src/test/ui/borrowck/issue-81365-5.rs create mode 100644 src/test/ui/borrowck/issue-81365-5.stderr create mode 100644 src/test/ui/borrowck/issue-81365-6.rs create mode 100644 src/test/ui/borrowck/issue-81365-6.stderr create mode 100644 src/test/ui/borrowck/issue-81365-7.rs create mode 100644 src/test/ui/borrowck/issue-81365-7.stderr create mode 100644 src/test/ui/borrowck/issue-81365-8.rs create mode 100644 src/test/ui/borrowck/issue-81365.rs create mode 100644 src/test/ui/borrowck/issue-81365.stderr diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index cd16a88e5fc3c..4bf4df226e172 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -8,11 +8,10 @@ use rustc_index::vec::Idx; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, - ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm, + ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; -use rustc_span::source_map::DesugaringKind; -use rustc_span::Span; +use rustc_middle::ty::{self, suggest_constraining_type_param, Instance, Ty}; +use rustc_span::{source_map::DesugaringKind, symbol::sym, Span}; use crate::dataflow::drop_flag_effects; use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex}; @@ -1543,6 +1542,36 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); + let tcx = self.infcx.tcx; + // point out implicit deref coercion + if let ( + Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }), + Some((method_did, method_substs)), + ) = ( + &self.body[loan.reserve_location.block].terminator, + crate::util::find_self_call( + tcx, + self.body, + loan.assigned_place.local, + loan.reserve_location.block, + ), + ) { + if tcx.is_diagnostic_item(sym::deref_method, method_did) { + let deref_target = + tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { + Instance::resolve(tcx, self.param_env, deref_target, method_substs) + .transpose() + }); + if let Some(Ok(instance)) = deref_target { + let deref_target_ty = instance.ty(tcx, self.param_env); + err.note(&format!( + "borrow occurs due to deref coercion to `{}`", + deref_target_ty + )); + } + } + } + err.buffer(&mut self.errors_buffer); } diff --git a/src/test/ui/borrowck/issue-81365-2.rs b/src/test/ui/borrowck/issue-81365-2.rs new file mode 100644 index 0000000000000..fbbdd93b97cc8 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-2.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.container.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-2.stderr b/src/test/ui/borrowck/issue-81365-2.stderr new file mode 100644 index 0000000000000..851cc4b1af29f --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-2.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-2.rs:25:9 + | +LL | let first = &self.container.target_field; + | -------------- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-3.rs b/src/test/ui/borrowck/issue-81365-3.rs new file mode 100644 index 0000000000000..9a9e3a3135822 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-3.rs @@ -0,0 +1,37 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-3.stderr b/src/test/ui/borrowck/issue-81365-3.stderr new file mode 100644 index 0000000000000..eedbed3cfe6c1 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-3.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-3.rs:32:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-4.rs b/src/test/ui/borrowck/issue-81365-4.rs new file mode 100644 index 0000000000000..b2643eb3358ac --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-4.rs @@ -0,0 +1,38 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, + outer_field: bool, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.outer_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-4.stderr b/src/test/ui/borrowck/issue-81365-4.stderr new file mode 100644 index 0000000000000..82c9fbbc16f6b --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-4.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.outer_field` because it is borrowed + --> $DIR/issue-81365-4.rs:33:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.outer_field` occurs here +LL | self.outer_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.outer_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-5.rs b/src/test/ui/borrowck/issue-81365-5.rs new file mode 100644 index 0000000000000..d36b79615e3ad --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-5.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} + +impl DerefTarget { + fn get(&self) -> &bool { + &self.target_field + } +} + +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = self.get(); + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-5.stderr b/src/test/ui/borrowck/issue-81365-5.stderr new file mode 100644 index 0000000000000..8085faf82ed06 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-5.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-5.rs:28:9 + | +LL | let first = self.get(); + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-6.rs b/src/test/ui/borrowck/issue-81365-6.rs new file mode 100644 index 0000000000000..85ea77756b3ba --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-6.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; + +struct Container { + target: Vec<()>, + container_field: bool, +} + +impl Deref for Container { + type Target = [()]; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self[0]; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-6.stderr b/src/test/ui/borrowck/issue-81365-6.stderr new file mode 100644 index 0000000000000..d35d12b9a8b5d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-6.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-6.rs:18:9 + | +LL | let first = &self[0]; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `[()]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-7.rs b/src/test/ui/borrowck/issue-81365-7.rs new file mode 100644 index 0000000000000..cbf70f11a9acf --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-7.rs @@ -0,0 +1,24 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +fn bad_borrow(c: &mut Container) { + let first = &c.target_field; + c.container_field = true; //~ ERROR E0506 + first; +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-7.stderr b/src/test/ui/borrowck/issue-81365-7.stderr new file mode 100644 index 0000000000000..0ee9fb8282112 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-7.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `c.container_field` because it is borrowed + --> $DIR/issue-81365-7.rs:20:5 + | +LL | let first = &c.target_field; + | - borrow of `c.container_field` occurs here +LL | c.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `c.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-8.rs b/src/test/ui/borrowck/issue-81365-8.rs new file mode 100644 index 0000000000000..0bb1033fb42f7 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-8.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &(*self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365.rs b/src/test/ui/borrowck/issue-81365.rs new file mode 100644 index 0000000000000..8e212a7701647 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365.stderr b/src/test/ui/borrowck/issue-81365.stderr new file mode 100644 index 0000000000000..a7dc5366f807e --- /dev/null +++ b/src/test/ui/borrowck/issue-81365.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365.rs:21:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. From 8412da6829cd9f71f33a039a24ea3470f586f250 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Tue, 2 Feb 2021 03:20:56 +1100 Subject: [PATCH 2/4] Add tests --- .../{issue-81365.rs => issue-81365-1.rs} | 0 ...ssue-81365.stderr => issue-81365-1.stderr} | 2 +- src/test/ui/borrowck/issue-81365-10.rs | 26 +++++++++++++++ src/test/ui/borrowck/issue-81365-10.stderr | 13 ++++++++ src/test/ui/borrowck/issue-81365-11.rs | 32 +++++++++++++++++++ src/test/ui/borrowck/issue-81365-11.stderr | 13 ++++++++ src/test/ui/borrowck/issue-81365-8.stderr | 15 +++++++++ src/test/ui/borrowck/issue-81365-9.rs | 26 +++++++++++++++ src/test/ui/borrowck/issue-81365-9.stderr | 13 ++++++++ 9 files changed, 139 insertions(+), 1 deletion(-) rename src/test/ui/borrowck/{issue-81365.rs => issue-81365-1.rs} (100%) rename src/test/ui/borrowck/{issue-81365.stderr => issue-81365-1.stderr} (94%) create mode 100644 src/test/ui/borrowck/issue-81365-10.rs create mode 100644 src/test/ui/borrowck/issue-81365-10.stderr create mode 100644 src/test/ui/borrowck/issue-81365-11.rs create mode 100644 src/test/ui/borrowck/issue-81365-11.stderr create mode 100644 src/test/ui/borrowck/issue-81365-8.stderr create mode 100644 src/test/ui/borrowck/issue-81365-9.rs create mode 100644 src/test/ui/borrowck/issue-81365-9.stderr diff --git a/src/test/ui/borrowck/issue-81365.rs b/src/test/ui/borrowck/issue-81365-1.rs similarity index 100% rename from src/test/ui/borrowck/issue-81365.rs rename to src/test/ui/borrowck/issue-81365-1.rs diff --git a/src/test/ui/borrowck/issue-81365.stderr b/src/test/ui/borrowck/issue-81365-1.stderr similarity index 94% rename from src/test/ui/borrowck/issue-81365.stderr rename to src/test/ui/borrowck/issue-81365-1.stderr index a7dc5366f807e..f680cd629d2fc 100644 --- a/src/test/ui/borrowck/issue-81365.stderr +++ b/src/test/ui/borrowck/issue-81365-1.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed - --> $DIR/issue-81365.rs:21:9 + --> $DIR/issue-81365-1.rs:21:9 | LL | let first = &self.target_field; | ---- borrow of `self.container_field` occurs here diff --git a/src/test/ui/borrowck/issue-81365-10.rs b/src/test/ui/borrowck/issue-81365-10.rs new file mode 100644 index 0000000000000..7602e184a9f9d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-10.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.deref().target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-10.stderr b/src/test/ui/borrowck/issue-81365-10.stderr new file mode 100644 index 0000000000000..891f70ed7f6b4 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-10.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-10.rs:21:9 + | +LL | let first = &self.deref().target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-11.rs b/src/test/ui/borrowck/issue-81365-11.rs new file mode 100644 index 0000000000000..6b558c65d3d61 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-11.rs @@ -0,0 +1,32 @@ +use std::ops::{Deref, DerefMut}; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl DerefMut for Container { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &mut self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-11.stderr b/src/test/ui/borrowck/issue-81365-11.stderr new file mode 100644 index 0000000000000..0770c136632db --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-11.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-11.rs:27:9 + | +LL | let first = &mut self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-8.stderr b/src/test/ui/borrowck/issue-81365-8.stderr new file mode 100644 index 0000000000000..0656c65c8232d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-8.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-8.rs:21:9 + | +LL | let first = &(*self).target_field; + | ------- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-9.rs b/src/test/ui/borrowck/issue-81365-9.rs new file mode 100644 index 0000000000000..cd57afa288df7 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-9.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &Deref::deref(self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-9.stderr b/src/test/ui/borrowck/issue-81365-9.stderr new file mode 100644 index 0000000000000..c7d48214fd4a8 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-9.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-9.rs:21:9 + | +LL | let first = &Deref::deref(self).target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. From 99f45732646443253524a3e85cb102d3b9430c6f Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Fri, 19 Feb 2021 13:30:49 +1100 Subject: [PATCH 3/4] Add deref definition location Update conflict_errors.rs Add deref definition location --- .../src/borrow_check/diagnostics/conflict_errors.rs | 1 + src/test/ui/borrowck/issue-81365-1.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-2.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-3.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-4.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-5.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-6.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-7.stderr | 5 +++++ src/test/ui/borrowck/issue-81365-8.stderr | 5 +++++ 9 files changed, 41 insertions(+) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 4bf4df226e172..f5bd497135ff3 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1568,6 +1568,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "borrow occurs due to deref coercion to `{}`", deref_target_ty )); + err.span_note(tcx.def_span(instance.def_id()), "deref defined here"); } } } diff --git a/src/test/ui/borrowck/issue-81365-1.stderr b/src/test/ui/borrowck/issue-81365-1.stderr index f680cd629d2fc..ef88d7f14a39b 100644 --- a/src/test/ui/borrowck/issue-81365-1.stderr +++ b/src/test/ui/borrowck/issue-81365-1.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-1.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-2.stderr b/src/test/ui/borrowck/issue-81365-2.stderr index 851cc4b1af29f..e71edb509649f 100644 --- a/src/test/ui/borrowck/issue-81365-2.stderr +++ b/src/test/ui/borrowck/issue-81365-2.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-2.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-3.stderr b/src/test/ui/borrowck/issue-81365-3.stderr index eedbed3cfe6c1..70bb6bb93a94b 100644 --- a/src/test/ui/borrowck/issue-81365-3.stderr +++ b/src/test/ui/borrowck/issue-81365-3.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-3.rs:23:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-4.stderr b/src/test/ui/borrowck/issue-81365-4.stderr index 82c9fbbc16f6b..e714bb86d1cd2 100644 --- a/src/test/ui/borrowck/issue-81365-4.stderr +++ b/src/test/ui/borrowck/issue-81365-4.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-4.rs:24:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-5.stderr b/src/test/ui/borrowck/issue-81365-5.stderr index 8085faf82ed06..7c0e9f43bd0b0 100644 --- a/src/test/ui/borrowck/issue-81365-5.stderr +++ b/src/test/ui/borrowck/issue-81365-5.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-5.rs:19:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-6.stderr b/src/test/ui/borrowck/issue-81365-6.stderr index d35d12b9a8b5d..85ed6acca3d41 100644 --- a/src/test/ui/borrowck/issue-81365-6.stderr +++ b/src/test/ui/borrowck/issue-81365-6.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `[()]` +note: deref defined here + --> $DIR/issue-81365-6.rs:9:5 + | +LL | type Target = [()]; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-7.stderr b/src/test/ui/borrowck/issue-81365-7.stderr index 0ee9fb8282112..506732ec0c5b4 100644 --- a/src/test/ui/borrowck/issue-81365-7.stderr +++ b/src/test/ui/borrowck/issue-81365-7.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-7.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-8.stderr b/src/test/ui/borrowck/issue-81365-8.stderr index 0656c65c8232d..716b6e9b51fd0 100644 --- a/src/test/ui/borrowck/issue-81365-8.stderr +++ b/src/test/ui/borrowck/issue-81365-8.stderr @@ -9,6 +9,11 @@ LL | first; | ----- borrow later used here | = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-8.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error From 1847a6c0c100f75120d9f41cee22cbab503e081c Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Mon, 22 Feb 2021 19:08:44 +1100 Subject: [PATCH 4/4] Extract deref coercion explanation into method --- .../src/borrow_check/diagnostics/conflict_errors.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index f5bd497135ff3..b0b58a8d00367 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1542,8 +1542,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); + self.explain_deref_coercion(loan, &mut err); + + err.buffer(&mut self.errors_buffer); + } + + fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>) { let tcx = self.infcx.tcx; - // point out implicit deref coercion if let ( Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }), Some((method_did, method_substs)), @@ -1572,8 +1577,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } - - err.buffer(&mut self.errors_buffer); } /// Reports an illegal reassignment; for example, an assignment to