-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Add CoerceShared field-wise reborrow WF checks #157489
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #![allow(dead_code)] | ||
|
|
||
| use std::marker::PhantomData; | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| pub struct ForeignRef<'a> { | ||
| value: &'a i32, | ||
| } | ||
|
|
||
| // SAFETY invariant: the pointer is valid as `&'a i32`. | ||
|
Contributor
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. issue: Comment unrelated to test code. |
||
| #[derive(Clone, Copy)] | ||
| pub struct ForeignPtrRef<'a>((*const i32, PhantomData<&'a ()>)); | ||
|
Contributor
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. nitpick: The two types are subtly different to one another for no particular reason. |
||
|
|
||
| impl<'a> ForeignPtrRef<'a> { | ||
| pub fn new(r: &'a i32) -> Self { | ||
|
Contributor
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. issue: Whole implementation part unrelated to test code. |
||
| ForeignPtrRef((r, PhantomData)) | ||
| } | ||
|
|
||
| pub fn to_ref(self) -> &'a i32 { | ||
| unsafe { &*self.0.0 } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| //@ check-pass | ||
|
|
||
| #![feature(reborrow)] | ||
| #![allow(dead_code)] | ||
|
|
||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| trait Trait { | ||
| type Assoc; | ||
| } | ||
|
|
||
| impl Trait for i32 { | ||
| type Assoc = i64; | ||
| } | ||
|
|
||
| struct MyMut<'a> { | ||
| x: &'a (), | ||
| y: i64, | ||
| } | ||
|
|
||
| #[derive(Copy, Clone)] | ||
| struct MyRef<'a> { | ||
| x: &'a (), | ||
| y: <i32 as Trait>::Assoc, | ||
| } | ||
|
|
||
| impl Reborrow for MyMut<'_> {} | ||
|
|
||
| impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {} | ||
|
|
||
| fn main() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| //@ check-pass | ||
|
|
||
| #![feature(reborrow, decl_macro)] | ||
| #![allow(incomplete_features)] | ||
|
|
||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| macro my_macro($field:ident) { | ||
| pub struct MyMut<'a> { | ||
| $field: &'a i32, | ||
| field: &'a i64, | ||
| } | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| pub struct MyRef<'a> { | ||
| $field: &'a i32, | ||
| field: &'a i64, | ||
| } | ||
|
|
||
| impl Reborrow for MyMut<'_> {} | ||
|
|
||
| impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {} | ||
| } | ||
|
|
||
| my_macro!(field); | ||
|
|
||
| fn main() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| //@ normalize-stderr: "\n\n\z" -> "\n" | ||
|
Contributor
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. nitpick: This does not appear anywhere in the code base currently. Normally this normalisation is used to deal with various platform-dependent outputs and random sources. This sort of "let's make the stderr file a little smaller in size" seems like an unnecessary complication. |
||
|
|
||
| #![feature(reborrow)] | ||
|
|
||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| struct MyMut<'a> { | ||
| x: &'static (), | ||
| y: &'a (), | ||
| } | ||
|
|
||
| impl Reborrow for MyMut<'_> {} | ||
|
|
||
| #[derive(Copy, Clone)] | ||
| struct MyRef<'a> { | ||
| x: &'a (), | ||
| //~^ ERROR | ||
| y: &'static (), | ||
| } | ||
|
|
||
| impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {} | ||
|
|
||
| fn main() {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field | ||
| --> $DIR/coerce-shared-field-lifetime-swap.rs:16:5 | ||
| | | ||
| LL | x: &'static (), | ||
| | -------------- source field `x` has type `&'static ()` | ||
| ... | ||
| LL | x: &'a (), | ||
| | ^^^^^^^^^ target field `x` has type `&'a ()` | ||
|
|
||
| error: aborting due to 1 previous error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| //@ normalize-stderr: "\n\n\z" -> "\n" | ||
|
|
||
| #![feature(reborrow)] | ||
|
|
||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| struct CustomMut<'a, T> { | ||
| value: &'a mut T, | ||
| } | ||
|
|
||
| impl<'a, T> Reborrow for CustomMut<'a, T> {} | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| struct CustomRef<'a, T> { | ||
| value: &'a T, | ||
| } | ||
|
|
||
| impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {} | ||
|
|
||
| struct RenamedMut<'a, T> { | ||
| source: &'a mut T, | ||
| } | ||
|
|
||
| impl<'a, T> Reborrow for RenamedMut<'a, T> {} | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| struct RenamedRef<'a, T> { | ||
| target: &'a T, | ||
| //~^ ERROR | ||
| } | ||
|
|
||
| impl<'a, T> CoerceShared<RenamedRef<'a, T>> for RenamedMut<'a, T> {} | ||
|
|
||
| struct BadMut<'a, T> { | ||
| value: &'a mut T, | ||
| } | ||
|
|
||
| impl<'a, T> Reborrow for BadMut<'a, T> {} | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| struct BadRef<'a, T> { | ||
| value: &'a u32, | ||
| //~^ ERROR | ||
| _marker: std::marker::PhantomData<T>, | ||
| } | ||
|
|
||
| impl<'a, T> CoerceShared<BadRef<'a, T>> for BadMut<'a, T> {} | ||
|
|
||
| fn good(_value: CustomRef<'_, u32>) {} | ||
|
|
||
| fn main() { | ||
| let mut value = 1; | ||
| good(CustomMut { value: &mut value }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| error: implementing `CoerceShared` requires every target field to have a corresponding source field | ||
| --> $DIR/coerce-shared-field-relations.rs:28:5 | ||
| | | ||
| LL | target: &'a T, | ||
| | ^^^^^^^^^^^^^ | ||
|
|
||
| error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field | ||
| --> $DIR/coerce-shared-field-relations.rs:42:5 | ||
| | | ||
| LL | value: &'a mut T, | ||
| | ---------------- source field `value` has type `&'a mut T` | ||
| ... | ||
| LL | value: &'a u32, | ||
| | ^^^^^^^^^^^^^^ target field `value` has type `&'a u32` | ||
|
|
||
| error: aborting due to 2 previous errors |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //@ normalize-stderr: "\n\n\z" -> "\n" | ||
|
|
||
| //@ aux-build: reborrow_foreign_private.rs | ||
|
|
||
| #![feature(reborrow)] | ||
|
|
||
| extern crate reborrow_foreign_private; | ||
|
|
||
| use reborrow_foreign_private::ForeignRef; | ||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| struct LocalMut<'a> { | ||
| value: &'a mut i32, | ||
| } | ||
|
|
||
| impl<'a> Reborrow for LocalMut<'a> {} | ||
|
|
||
| impl<'a> CoerceShared<ForeignRef<'a>> for LocalMut<'a> {} | ||
| //~^ ERROR | ||
|
|
||
| fn main() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| error: implementing `CoerceShared` requires all source and target fields to be accessible from the impl | ||
| --> $DIR/coerce-shared-foreign-private-field.rs:18:1 | ||
| | | ||
| LL | impl<'a> CoerceShared<ForeignRef<'a>> for LocalMut<'a> {} | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| error: aborting due to 1 previous error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| //@ normalize-stderr: "\n\n\z" -> "\n" | ||
|
|
||
| //@ aux-build: reborrow_foreign_private.rs | ||
|
|
||
| #![feature(reborrow)] | ||
|
|
||
| extern crate reborrow_foreign_private; | ||
|
|
||
| use reborrow_foreign_private::ForeignPtrRef; | ||
| use std::marker::{CoerceShared, PhantomData, Reborrow}; | ||
| use std::ptr; | ||
|
|
||
| struct LocalPtrMut<'a>((*const i32, PhantomData<&'a ()>)); | ||
|
|
||
| impl<'a> Reborrow for LocalPtrMut<'a> {} | ||
|
|
||
| impl<'a> CoerceShared<ForeignPtrRef<'a>> for LocalPtrMut<'a> {} | ||
| //~^ ERROR | ||
|
|
||
| fn main() { | ||
| let local = LocalPtrMut((ptr::null(), PhantomData)); | ||
|
Contributor
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. issue: This code here is not related to what is actually being tested here AFAIU. The LocalMut/ForeignRef test above does not have anything in main. |
||
| let foreign: ForeignPtrRef<'_> = local; | ||
| let _ = foreign.to_ref(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| error: implementing `CoerceShared` requires all source and target fields to be accessible from the impl | ||
| --> $DIR/coerce-shared-foreign-private-tuple-field.rs:17:1 | ||
| | | ||
| LL | impl<'a> CoerceShared<ForeignPtrRef<'a>> for LocalPtrMut<'a> {} | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| error: aborting due to 1 previous error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #![feature(reborrow)] | ||
|
|
||
| use std::marker::{CoerceShared, PhantomData, Reborrow}; | ||
|
|
||
| struct CustomMarker<'a>(PhantomData<&'a ()>); | ||
|
|
||
| impl<'a> Reborrow for CustomMarker<'a> {} | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| struct StaticMarkerRef<'a>(PhantomData<&'a ()>); | ||
|
|
||
| impl<'a> CoerceShared<StaticMarkerRef<'static>> for CustomMarker<'a> {} | ||
| //~^ ERROR | ||
|
|
||
| fn method(_a: StaticMarkerRef<'static>) {} | ||
|
|
||
| fn main() { | ||
| let a = CustomMarker(PhantomData); | ||
| method(a); | ||
| //~^ ERROR | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| error: implementing `CoerceShared` requires source and target to use the same reborrow lifetime argument | ||
| --> $DIR/coerce-shared-lifetime-mismatch.rs:12:10 | ||
| | | ||
| LL | impl<'a> CoerceShared<StaticMarkerRef<'static>> for CustomMarker<'a> {} | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| error[E0597]: `a` does not live long enough | ||
| --> $DIR/coerce-shared-lifetime-mismatch.rs:19:12 | ||
| | | ||
| LL | let a = CustomMarker(PhantomData); | ||
| | - binding `a` declared here | ||
| LL | method(a); | ||
|
Contributor
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. thought: Huh... this seems confusing to me: if we've given an error from the |
||
| | -------^- | ||
| | | | | ||
| | | borrowed value does not live long enough | ||
| | argument requires that `a` is borrowed for `'static` | ||
| LL | | ||
| LL | } | ||
| | - `a` dropped here while still borrowed | ||
|
|
||
| error: aborting due to 2 previous errors | ||
|
|
||
| For more information about this error, try `rustc --explain E0597`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //@ normalize-stderr: "\n\n\z" -> "\n" | ||
|
|
||
| #![feature(reborrow)] | ||
|
|
||
| use std::marker::{CoerceShared, Reborrow}; | ||
|
|
||
| struct MissingSourceMut<'a, T> { | ||
| value: &'a mut T, | ||
| } | ||
|
|
||
| impl<'a, T> Reborrow for MissingSourceMut<'a, T> {} | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| struct MissingSourceRef<'a, T> { | ||
| value: &'a T, | ||
| len: usize, | ||
| //~^ ERROR | ||
| } | ||
|
|
||
| impl<'a, T> CoerceShared<MissingSourceRef<'a, T>> for MissingSourceMut<'a, T> {} | ||
|
|
||
| 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.
thought: I believe you could move the
ForeignPtrRefinto amod foreign_ptr {}block inside the actual test file.