Skip to content

Commit e789c33

Browse files
committed
Add missing tests and adress concerns
1 parent f3ef3bd commit e789c33

39 files changed

Lines changed: 1137 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//@ known-bug: unknown
2+
#![feature(reborrow)]
3+
#![allow(dead_code)]
4+
5+
use std::marker::{CoerceShared, Reborrow};
6+
7+
// This test combines alias/projection normalization with the leaf `&mut T` to `&T`
8+
// shared reborrow path.
9+
10+
struct InnerMut<'a, T> {
11+
value: &'a mut T,
12+
}
13+
14+
impl<'a, T> Reborrow for InnerMut<'a, T> {}
15+
16+
struct InnerRef<'a, T> {
17+
value: &'a T,
18+
}
19+
20+
impl<'a, T> Clone for InnerRef<'a, T> {
21+
fn clone(&self) -> Self {
22+
*self
23+
}
24+
}
25+
26+
impl<'a, T> Copy for InnerRef<'a, T> {}
27+
28+
impl<'a, T> CoerceShared<InnerRef<'a, T>> for InnerMut<'a, T> {}
29+
30+
type DirectInnerRef<'a, T> = InnerRef<'a, T>;
31+
32+
trait RefFamily<'a, T> {
33+
type Ref;
34+
}
35+
36+
struct Projected;
37+
38+
impl<'a, T: 'a> RefFamily<'a, T> for Projected {
39+
type Ref = InnerRef<'a, T>;
40+
}
41+
42+
type ProjectedInnerRef<'a, T> = <Projected as RefFamily<'a, T>>::Ref;
43+
44+
struct OuterMut<'a, T> {
45+
inner: InnerMut<'a, T>,
46+
tag: usize,
47+
}
48+
49+
impl<'a, T> Reborrow for OuterMut<'a, T> {}
50+
51+
struct OuterAliasRef<'a, T> {
52+
inner: DirectInnerRef<'a, T>,
53+
tag: usize,
54+
}
55+
56+
impl<'a, T> Clone for OuterAliasRef<'a, T> {
57+
fn clone(&self) -> Self {
58+
*self
59+
}
60+
}
61+
62+
impl<'a, T> Copy for OuterAliasRef<'a, T> {}
63+
64+
impl<'a, T> CoerceShared<OuterAliasRef<'a, T>> for OuterMut<'a, T> {}
65+
66+
struct OuterProjectionRef<'a, T: 'a> {
67+
inner: ProjectedInnerRef<'a, T>,
68+
tag: usize,
69+
}
70+
71+
impl<'a, T: 'a> Clone for OuterProjectionRef<'a, T> {
72+
fn clone(&self) -> Self {
73+
*self
74+
}
75+
}
76+
77+
impl<'a, T: 'a> Copy for OuterProjectionRef<'a, T> {}
78+
79+
impl<'a, T: 'a> CoerceShared<OuterProjectionRef<'a, T>> for OuterMut<'a, T> {}
80+
81+
fn read_alias<'a>(outer: OuterAliasRef<'a, u32>) -> (&'a u32, usize) {
82+
(outer.inner.value, outer.tag)
83+
}
84+
85+
fn read_projection<'a>(outer: OuterProjectionRef<'a, u32>) -> (&'a u32, usize) {
86+
(outer.inner.value, outer.tag)
87+
}
88+
89+
const fn const_accept_projection(_outer: OuterProjectionRef<'_, u32>) {}
90+
91+
const fn consteval_projection_reborrow() {
92+
let mut value = 11;
93+
const_accept_projection(OuterMut {
94+
inner: InnerMut { value: &mut value },
95+
tag: 5,
96+
});
97+
}
98+
99+
fn main() {
100+
const { consteval_projection_reborrow(); }
101+
102+
let mut value = 22;
103+
let outer = OuterMut { inner: InnerMut { value: &mut value }, tag: 7 };
104+
105+
let (alias_value, alias_tag) = read_alias(outer);
106+
assert_eq!((*alias_value, alias_tag), (22, 7));
107+
108+
let (projection_value, projection_tag) = read_projection(outer);
109+
assert_eq!((*projection_value, projection_tag), (22, 7));
110+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//@ known-bug: unknown
2+
#![feature(reborrow)]
3+
#![allow(dead_code)]
4+
5+
use std::marker::{CoerceShared, PhantomData, Reborrow};
6+
use std::ptr::NonNull;
7+
8+
struct ImbrisMut<'a, T> {
9+
ptr: NonNull<T>,
10+
metadata: usize,
11+
marker: PhantomData<&'a mut T>,
12+
}
13+
14+
impl<'a, T> Reborrow for ImbrisMut<'a, T> {}
15+
16+
struct ImbrisRef<'a, T> {
17+
ptr: NonNull<T>,
18+
marker: PhantomData<&'a T>,
19+
}
20+
21+
impl<'a, T> Clone for ImbrisRef<'a, T> {
22+
fn clone(&self) -> Self {
23+
*self
24+
}
25+
}
26+
27+
impl<'a, T> Copy for ImbrisRef<'a, T> {}
28+
29+
impl<'a, T> CoerceShared<ImbrisRef<'a, T>> for ImbrisMut<'a, T> {}
30+
31+
fn ptr(value: ImbrisRef<'_, i32>) -> NonNull<i32> {
32+
value.ptr
33+
}
34+
35+
fn main() {
36+
let mut value = 1;
37+
let raw = NonNull::from(&mut value);
38+
let wrapped = ImbrisMut { ptr: raw, metadata: 32, marker: PhantomData };
39+
40+
assert_eq!(ptr(wrapped), raw);
41+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ known-bug: unknown
2+
//@ edition: 2024
3+
4+
#![feature(reborrow)]
5+
6+
use std::marker::{CoerceShared, PhantomData, Reborrow};
7+
8+
struct CustomMarker<'a>(PhantomData<&'a ()>);
9+
struct CustomMarkerRef;
10+
11+
impl<'a> Reborrow for CustomMarker<'a> {}
12+
impl<'a> CoerceShared<CustomMarkerRef> for CustomMarker<'a> {}
13+
//~^ ERROR
14+
15+
fn method(_a: CustomMarkerRef) {}
16+
17+
fn main() {
18+
let a = CustomMarker(PhantomData);
19+
method(a);
20+
//~^ ERROR
21+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//@ known-bug: unknown
2+
#![feature(reborrow)]
3+
#![allow(dead_code)]
4+
5+
use std::marker::{CoerceShared, PhantomData, Reborrow};
6+
use std::ptr::NonNull;
7+
8+
struct MatMut<'a, T> {
9+
ptr: NonNull<T>,
10+
rows: usize,
11+
cols: usize,
12+
row_stride: usize,
13+
col_stride: usize,
14+
marker: PhantomData<&'a mut T>,
15+
}
16+
17+
impl<'a, T> Reborrow for MatMut<'a, T> {}
18+
19+
struct MatRef<'a, T> {
20+
ptr: NonNull<T>,
21+
rows: usize,
22+
cols: usize,
23+
row_stride: usize,
24+
col_stride: usize,
25+
marker: PhantomData<&'a T>,
26+
}
27+
28+
impl<'a, T> Clone for MatRef<'a, T> {
29+
fn clone(&self) -> Self {
30+
*self
31+
}
32+
}
33+
34+
impl<'a, T> Copy for MatRef<'a, T> {}
35+
36+
impl<'a, T> CoerceShared<MatRef<'a, T>> for MatMut<'a, T> {}
37+
38+
fn dims<T>(mat: MatRef<'_, T>) -> (usize, usize, usize, usize) {
39+
let _ = mat.ptr;
40+
(mat.rows, mat.cols, mat.row_stride, mat.col_stride)
41+
}
42+
43+
fn main() {
44+
let mut value = 0;
45+
let mat = MatMut {
46+
ptr: NonNull::from(&mut value),
47+
rows: 2,
48+
cols: 3,
49+
row_stride: 4,
50+
col_stride: 5,
51+
marker: PhantomData,
52+
};
53+
54+
assert_eq!(dims(mat), (2, 3, 4, 5));
55+
// Reusing the same source proves repeated shared reborrows keep source-only data protected
56+
// without consuming the reborrowable value.
57+
assert_eq!(dims(mat), (2, 3, 4, 5));
58+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//@ known-bug: unknown
2+
#![feature(reborrow)]
3+
#![allow(dead_code)]
4+
5+
use std::marker::{CoerceShared, Reborrow};
6+
7+
struct InnerMut<'a, T> {
8+
value: &'a mut T,
9+
}
10+
11+
impl<'a, T> Reborrow for InnerMut<'a, T> {}
12+
13+
struct InnerRef<'a, T> {
14+
value: &'a T,
15+
}
16+
17+
impl<'a, T> Clone for InnerRef<'a, T> {
18+
fn clone(&self) -> Self {
19+
*self
20+
}
21+
}
22+
23+
impl<'a, T> Copy for InnerRef<'a, T> {}
24+
25+
impl<'a, T> CoerceShared<InnerRef<'a, T>> for InnerMut<'a, T> {}
26+
27+
struct OuterMut<'a, T> {
28+
inner: InnerMut<'a, T>,
29+
tag: usize,
30+
}
31+
32+
impl<'a, T> Reborrow for OuterMut<'a, T> {}
33+
34+
struct OuterRef<'a, T> {
35+
inner: InnerRef<'a, T>,
36+
tag: usize,
37+
}
38+
39+
impl<'a, T> Clone for OuterRef<'a, T> {
40+
fn clone(&self) -> Self {
41+
*self
42+
}
43+
}
44+
45+
impl<'a, T> Copy for OuterRef<'a, T> {}
46+
47+
impl<'a, T> CoerceShared<OuterRef<'a, T>> for OuterMut<'a, T> {}
48+
49+
fn get<'a>(outer: OuterRef<'a, i32>) -> (&'a i32, usize) {
50+
(outer.inner.value, outer.tag)
51+
}
52+
53+
fn main() {
54+
let mut value = 22;
55+
let outer = OuterMut { inner: InnerMut { value: &mut value }, tag: 7 };
56+
57+
let (first, tag) = get(outer);
58+
assert_eq!((*first, tag), (22, 7));
59+
60+
let (second, tag) = get(outer);
61+
assert_eq!((*second, tag), (22, 7));
62+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//@ known-bug: unknown
2+
#![feature(reborrow)]
3+
#![allow(dead_code)]
4+
5+
use std::marker::{CoerceShared, PhantomData, Reborrow};
6+
7+
struct SourceLeadingMut<'a, T>(PhantomData<&'a mut T>, &'a mut T);
8+
9+
impl<'a, T> Reborrow for SourceLeadingMut<'a, T> {}
10+
11+
struct SourceLeadingRef<'a, T>(&'a T);
12+
13+
impl<'a, T> Clone for SourceLeadingRef<'a, T> {
14+
fn clone(&self) -> Self {
15+
*self
16+
}
17+
}
18+
19+
impl<'a, T> Copy for SourceLeadingRef<'a, T> {}
20+
21+
impl<'a, T> CoerceShared<SourceLeadingRef<'a, T>> for SourceLeadingMut<'a, T> {}
22+
23+
struct TargetLeadingMut<'a, T>(&'a mut T);
24+
25+
impl<'a, T> Reborrow for TargetLeadingMut<'a, T> {}
26+
27+
struct TargetLeadingRef<'a, T>(PhantomData<&'a T>, &'a T);
28+
29+
impl<'a, T> Clone for TargetLeadingRef<'a, T> {
30+
fn clone(&self) -> Self {
31+
*self
32+
}
33+
}
34+
35+
impl<'a, T> Copy for TargetLeadingRef<'a, T> {}
36+
37+
impl<'a, T> CoerceShared<TargetLeadingRef<'a, T>> for TargetLeadingMut<'a, T> {}
38+
39+
struct InterleavedMut<'a, T, U>(
40+
PhantomData<&'a mut T>,
41+
&'a mut T,
42+
PhantomData<&'a mut U>,
43+
&'a mut U,
44+
);
45+
46+
impl<'a, T, U> Reborrow for InterleavedMut<'a, T, U> {}
47+
48+
struct InterleavedRef<'a, T, U>(&'a T, PhantomData<&'a T>, &'a U, PhantomData<&'a U>);
49+
50+
impl<'a, T, U> Clone for InterleavedRef<'a, T, U> {
51+
fn clone(&self) -> Self {
52+
*self
53+
}
54+
}
55+
56+
impl<'a, T, U> Copy for InterleavedRef<'a, T, U> {}
57+
58+
impl<'a, T, U> CoerceShared<InterleavedRef<'a, T, U>> for InterleavedMut<'a, T, U> {}
59+
60+
fn read_source_leading<'a>(value: SourceLeadingRef<'a, i32>) -> &'a i32 {
61+
value.0
62+
}
63+
64+
fn read_target_leading<'a>(value: TargetLeadingRef<'a, i32>) -> &'a i32 {
65+
value.1
66+
}
67+
68+
fn read_interleaved<'a>(value: InterleavedRef<'a, i32, i64>) -> (&'a i32, &'a i64) {
69+
(value.0, value.2)
70+
}
71+
72+
fn main() {
73+
let mut source_leading = 10;
74+
let wrapped = SourceLeadingMut(PhantomData, &mut source_leading);
75+
assert_eq!(*read_source_leading(wrapped), 10);
76+
77+
let mut target_leading = 20;
78+
let wrapped = TargetLeadingMut(&mut target_leading);
79+
assert_eq!(*read_target_leading(wrapped), 20);
80+
81+
let mut first = 30;
82+
let mut second = 40_i64;
83+
let wrapped = InterleavedMut(PhantomData, &mut first, PhantomData, &mut second);
84+
let (first, second) = read_interleaved(wrapped);
85+
assert_eq!((*first, *second), (30, 40));
86+
}

0 commit comments

Comments
 (0)