-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Point out implicit deref coercions in borrow #81629
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
Comment on lines
+1
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason the different tests couldn't be merged into fewer files? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I don't understand the previous phases that transformed the code into MIR, so I made some tests with the intent of something like "what happens to double implicit derefs?", "what happens to indexing and function calls?", "what happens with implicitly inserted v. explicitly inserted derefs?". The only reasons I haven't merged them is because I don't know enough to decide what distinctions in the tests are important, and also that I'm not sure if any existing tests cover what I've already written. If you think that some tests are redundant, I will remove them. |
||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
error[E0506]: cannot assign to `self.container_field` because it is borrowed | ||
--> $DIR/issue-81365-1.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` | ||
note: deref defined here | ||
--> $DIR/issue-81365-1.rs:12:5 | ||
| | ||
LL | type Target = DerefTarget; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0506`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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` | ||
note: deref defined here | ||
--> $DIR/issue-81365-2.rs:12:5 | ||
| | ||
LL | type Target = DerefTarget; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0506`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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` | ||
note: deref defined here | ||
--> $DIR/issue-81365-3.rs:23:5 | ||
| | ||
LL | type Target = Container; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0506`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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` | ||
note: deref defined here | ||
--> $DIR/issue-81365-4.rs:24:5 | ||
| | ||
LL | type Target = Container; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0506`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we move this code to a method with an appropriate name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved the code in my latest commit.