Skip to content

Commit 5433734

Browse files
committed
add lang items for field projections via virtual places
1 parent bcded33 commit 5433734

7 files changed

Lines changed: 310 additions & 2 deletions

File tree

compiler/rustc_hir/src/lang_items.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,33 @@ language_item_table! {
443443
FieldBase, sym::field_base, field_base, Target::AssocTy, GenericRequirement::Exact(0);
444444
FieldType, sym::field_type, field_type, Target::AssocTy, GenericRequirement::Exact(0);
445445
FieldOffset, sym::field_offset, field_offset, Target::AssocConst, GenericRequirement::Exact(0);
446+
447+
// Field projections lang-items.
448+
Projection, sym::projection, projection, Target::Trait, GenericRequirement::Exact(0);
449+
ProjectionSource, sym::projection_source, projection_source, Target::AssocTy, GenericRequirement::Exact(0);
450+
ProjectionTarget, sym::projection_target, projection_target, Target::AssocTy, GenericRequirement::Exact(0);
451+
ProjectionOffset, sym::projection_offset, projection_offset, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
452+
HasPlace, sym::has_place, has_place, Target::Trait, GenericRequirement::Exact(0);
453+
HasPlaceTarget, sym::has_place_target, has_place_target, Target::AssocTy, GenericRequirement::Exact(0);
454+
PlaceRead, sym::place_read, place_read, Target::Trait, GenericRequirement::Exact(1);
455+
PlaceReadSafety, sym::place_read_safety, place_read_safety, Target::AssocConst, GenericRequirement::Exact(1);
456+
PlaceReadRead, sym::place_read_read, place_read_read, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
457+
PlaceWrite, sym::place_write, place_write, Target::Trait, GenericRequirement::Exact(1);
458+
PlaceWriteSafety, sym::place_write_safety, place_write_safety, Target::AssocConst, GenericRequirement::Exact(1);
459+
PlaceWriteWrite, sym::place_write_write, place_write_write, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
460+
PlaceMove, sym::place_move, place_move, Target::Trait, GenericRequirement::Exact(1);
461+
PlaceDrop, sym::place_drop, place_drop, Target::Trait, GenericRequirement::Exact(1);
462+
PlaceDropDrop, sym::place_drop_drop, place_drop_drop, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
463+
DropHusk, sym::drop_husk, drop_husk, Target::Trait, GenericRequirement::Exact(0);
464+
DropHuskDropHusk, sym::drop_husk_drop_husk, drop_husk_drop_husk, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
465+
PlaceBorrow, sym::place_borrow, place_borrow, Target::Trait, GenericRequirement::Exact(2);
466+
PlaceBorrowSafety, sym::place_borrow_safety, place_borrow_safety, Target::AssocConst, GenericRequirement::Exact(2);
467+
PlaceBorrowBorrow, sym::place_borrow_borrow, place_borrow_borrow, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(2);
468+
PlaceDeref, sym::place_deref, place_deref, Target::Trait, GenericRequirement::Exact(1);
469+
PlaceDerefDeref, sym::place_deref_deref, place_deref_deref, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
470+
PlaceWrapper, sym::place_wrapper, place_wrapper, Target::Trait, GenericRequirement::Exact(1);
471+
PlaceWrapperWrappedProjection, sym::place_wrapper_wrapped_projection, place_wrapper_wrapped_projection, Target::AssocTy, GenericRequirement::Exact(1);
472+
PlaceWrapperWrapProjection, sym::place_wrapper_wrap_projection, place_wrapper_wrap_projection, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
446473
}
447474

448475
/// The requirement imposed on the generics of a lang item

compiler/rustc_span/src/symbol.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,8 @@ symbols! {
828828
dreg_low8,
829829
dreg_low16,
830830
drop,
831+
drop_husk,
832+
drop_husk_drop_husk,
831833
drop_in_place,
832834
drop_types_in_const,
833835
dropck_eyepatch,
@@ -1031,6 +1033,8 @@ symbols! {
10311033
guard_patterns,
10321034
half_open_range_patterns,
10331035
half_open_range_patterns_in_slices,
1036+
has_place,
1037+
has_place_target,
10341038
hash,
10351039
hexagon,
10361040
hexagon_target_feature,
@@ -1501,6 +1505,23 @@ symbols! {
15011505
pin,
15021506
pin_ergonomics,
15031507
pin_v2,
1508+
place_borrow,
1509+
place_borrow_borrow,
1510+
place_borrow_safety,
1511+
place_deref,
1512+
place_deref_deref,
1513+
place_drop,
1514+
place_drop_drop,
1515+
place_move,
1516+
place_read,
1517+
place_read_read,
1518+
place_read_safety,
1519+
place_wrapper,
1520+
place_wrapper_wrap_projection,
1521+
place_wrapper_wrapped_projection,
1522+
place_write,
1523+
place_write_safety,
1524+
place_write_write,
15041525
platform_intrinsics,
15051526
plugin,
15061527
plugin_registrar,
@@ -1552,6 +1573,10 @@ symbols! {
15521573
proc_macro_non_items,
15531574
proc_macro_path_invoc,
15541575
profiler_runtime,
1576+
projection,
1577+
projection_offset,
1578+
projection_source,
1579+
projection_target,
15551580
ptr,
15561581
ptr_cast,
15571582
ptr_cast_const,

library/core/src/field.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Field Reflection
22
33
use crate::marker::PhantomData;
4+
use crate::ptr::Pointee;
45

56
/// Field Representing Type
67
#[unstable(feature = "field_representing_type_raw", issue = "none")]
@@ -81,3 +82,35 @@ pub unsafe trait Field: Send + Sync + Copy {
8182
#[lang = "field_offset"]
8283
const OFFSET: usize = crate::intrinsics::field_offset::<Self>();
8384
}
85+
86+
/// A subplace of [`Self::Source`] with the type [`Self::Target`].
87+
///
88+
/// A subplace is always within the same allocation as the base place. Current subplaces are:
89+
/// - field accesses,
90+
/// - array/slice indexes.
91+
///
92+
/// This represents an arbitrary chaining of these; it can also be empty.
93+
///
94+
/// # Safety
95+
///
96+
/// FIXME
97+
#[unstable(feature = "field_projections", issue = "145383")]
98+
#[rustc_deny_explicit_impl]
99+
#[rustc_dyn_incompatible_trait]
100+
#[lang = "projection"]
101+
pub unsafe trait Projection: Sized + Copy {
102+
/// The type of the base place this subplace is a part of.
103+
#[lang = "projection_source"]
104+
type Source: ?Sized;
105+
106+
/// The type of this subplace.
107+
#[lang = "projection_target"]
108+
type Target: ?Sized;
109+
110+
/// The offset of this subplace.
111+
#[lang = "projection_offset"]
112+
fn offset(
113+
self,
114+
metadata: <Self::Source as Pointee>::Metadata,
115+
) -> (usize, <Self::Target as Pointee>::Metadata);
116+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
use crate::field::Projection;
2+
3+
/// Marks a type as containing a place.
4+
///
5+
/// This is the new trait for the dereference operator `*`; implementing it will allow writing `*x`
6+
/// for `x: Self`, but not enable any operations on `*x`. For those, one of the other place
7+
/// operation traits has to be implemented:
8+
///
9+
/// - [`PlaceRead`]
10+
/// - [`PlaceWrite`]
11+
/// - [`PlaceDrop`]
12+
/// - [`PlaceMove`]
13+
/// - [`PlaceBorrow`]
14+
/// - [`PlaceDeref`]
15+
#[unstable(feature = "field_projections", issue = "145383")]
16+
#[lang = "has_place"]
17+
pub trait HasPlace {
18+
/// The type of the contained place.
19+
#[lang = "has_place_target"]
20+
type Target: ?Sized;
21+
}
22+
23+
/// Reading a place `let val = *x;`.
24+
///
25+
/// When `x: Self`, then `let val = *x;` will be desugared into [`PlaceRead::read`].
26+
///
27+
/// # Safety
28+
///
29+
/// FIXME
30+
#[unstable(feature = "field_projections", issue = "145383")]
31+
#[lang = "place_read"]
32+
pub unsafe trait PlaceRead<P>: HasPlace
33+
where
34+
P: Projection<Source = Self::Target>,
35+
{
36+
/// Whether the read operation is safe when used through the operator.
37+
///
38+
/// When the compiler emits the call to `read`, the borrow checker guarantees that no other
39+
/// operation is conflicting with this one.
40+
#[lang = "place_read_safety"]
41+
const SAFETY: bool;
42+
43+
/// Read the `proj` subplace of the place pointed to by `this`.
44+
///
45+
/// # Safety
46+
///
47+
/// FIXME
48+
#[lang = "place_read_read"]
49+
unsafe fn read(this: *const Self, proj: P) -> P::Target;
50+
}
51+
52+
/// Writing a place `*x = val;`.
53+
///
54+
/// When `x: Self`, then `*x = val;` will be desugared into [`PlaceWrite::write`].
55+
///
56+
/// # Safety
57+
///
58+
/// FIXME
59+
#[unstable(feature = "field_projections", issue = "145383")]
60+
#[lang = "place_write"]
61+
pub unsafe trait PlaceWrite<P>: HasPlace
62+
where
63+
P: Projection<Source = Self::Target>,
64+
{
65+
/// Whether the write operation is safe when used through the operator.
66+
///
67+
/// When the compiler emits the call to `read`, the borrow checker guarantees that no other
68+
/// operation is conflicting with this one.
69+
#[lang = "place_write_safety"]
70+
const SAFETY: bool;
71+
72+
/// Write to the `proj` subplace of the place pointed to by `this`.
73+
///
74+
/// # Safety
75+
///
76+
/// FIXME
77+
#[lang = "place_write_write"]
78+
unsafe fn write(this: *const Self, proj: P, value: P::Target);
79+
}
80+
81+
/// Moving out of a place.
82+
///
83+
/// When `x: Self` and one performs a [`PlaceRead::read`] where the target value is not [`Copy`],
84+
/// then the compiler checks if this trait is implemented and if so, moves the value out by reading
85+
/// it and adjusting the borrow checker state of the place.
86+
///
87+
/// # Safety
88+
///
89+
/// FIXME
90+
#[unstable(feature = "field_projections", issue = "145383")]
91+
#[lang = "place_move"]
92+
pub unsafe trait PlaceMove<P>: PlaceRead<P>
93+
where
94+
P: Projection<Source = Self::Target>,
95+
{
96+
}
97+
98+
/// Dropping a place.
99+
///
100+
/// Emitted by the compiler when a place has been partially moved out and the pointer with ownership
101+
/// is being dropped.
102+
///
103+
/// # Safety
104+
///
105+
/// FIXME
106+
#[unstable(feature = "field_projections", issue = "145383")]
107+
#[lang = "place_drop"]
108+
pub unsafe trait PlaceDrop<P>: HasPlace
109+
where
110+
P: Projection<Source = Self::Target>,
111+
{
112+
/// Drop the `proj` subplace of the place pointed to by `this`.
113+
///
114+
/// # Safety
115+
///
116+
/// FIXME
117+
#[lang = "place_drop_drop"]
118+
unsafe fn drop(this: *const Self, proj: P);
119+
}
120+
121+
/// Dropping a pointer that points at a fully moved-out place.
122+
///
123+
/// This operation is emitted by the compiler when a pointer is being dropped that had some fields
124+
/// moved out.
125+
///
126+
/// # Safety
127+
///
128+
/// FIXME
129+
#[unstable(feature = "field_projections", issue = "145383")]
130+
#[lang = "drop_husk"]
131+
pub unsafe trait DropHusk: HasPlace {
132+
/// Drops the
133+
///
134+
/// # Safety
135+
///
136+
/// FIXME
137+
#[lang = "drop_husk_drop_husk"]
138+
unsafe fn drop_husk(this: *const Self);
139+
}
140+
141+
/// Borrowing a place with `X`.
142+
///
143+
/// When `y: Self`, then `let x = @<X> *y;` will be desugared into [`PlaceBorrow::borrow`].
144+
///
145+
/// # Safety
146+
///
147+
/// FIXME
148+
#[unstable(feature = "field_projections", issue = "145383")]
149+
#[lang = "place_borrow"]
150+
pub unsafe trait PlaceBorrow<P, X>: HasPlace
151+
where
152+
P: Projection<Source = Self::Target>,
153+
X: HasPlace<Target = P::Target>,
154+
{
155+
/// Whether the borrow operation is safe when used through the operator.
156+
///
157+
/// When the compiler emits the call to `read`, the borrow checker guarantees that no other
158+
/// operation is conflicting with this one.
159+
#[lang = "place_borrow_safety"]
160+
const SAFETY: bool;
161+
162+
/// Borrow the `proj` subplace of the place pointed to by `this` with `X`.
163+
///
164+
/// # Safety
165+
///
166+
/// FIXME
167+
#[lang = "place_borrow_borrow"]
168+
unsafe fn borrow(this: *const Self, proj: P) -> X;
169+
}
170+
171+
/// Accessing a nested pointer.
172+
///
173+
/// When `x: Self`, then nested dereferences `let _ = **x;` is desugared into a combination of the
174+
/// corresponding operation and a [`PlaceDeref::deref`].
175+
///
176+
/// # Safety
177+
///
178+
/// FIXME
179+
#[unstable(feature = "field_projections", issue = "145383")]
180+
#[lang = "place_deref"]
181+
pub unsafe trait PlaceDeref<P>: HasPlace
182+
where
183+
P: Projection<Source = Self::Target>,
184+
P::Target: HasPlace,
185+
{
186+
/// Obtain a raw pointer to the `proj` subplace of the place pointed to by `this`.
187+
///
188+
/// # Safety
189+
///
190+
/// FIXME
191+
#[lang = "place_deref_deref"]
192+
unsafe fn deref(ptr: *mut Self, proj: P) -> *const P::Target;
193+
}
194+
195+
/// Forwards the subplace `P` of the place contained by this.
196+
///
197+
/// When `x: Self` and `Self::Target` has a subplace `P` accessible via `.proj`, then `x.proj` also
198+
/// exists, has type `<Self::WrappedProjection as Projection>::Target` and any place operation on it
199+
/// uses <code>[Self::wrap_projection]\(proj\)</code> as the subplace.
200+
///
201+
/// # Safety
202+
///
203+
/// FIXME
204+
#[unstable(feature = "field_projections", issue = "145383")]
205+
#[lang = "place_wrapper"]
206+
pub unsafe trait PlaceWrapper<P>: HasPlace
207+
where
208+
P: Projection<Source = Self::Target>,
209+
{
210+
/// The projection to use instead of `P`.
211+
#[lang = "place_wrapper_wrapped_projection"]
212+
type WrappedProjection: Projection<Source = Self>;
213+
214+
/// Turn a projection of type `P` into [`Self::WrappedProjection`].
215+
#[lang = "place_wrapper_wrap_projection"]
216+
fn wrap_projection(proj: P) -> Self::WrappedProjection;
217+
}

library/core/src/ops/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ mod control_flow;
145145
mod coroutine;
146146
mod deref;
147147
mod drop;
148+
mod field_projections;
148149
mod function;
149150
mod index;
150151
mod index_range;
@@ -177,6 +178,11 @@ pub use self::deref::Receiver;
177178
pub use self::deref::{Deref, DerefMut};
178179
#[stable(feature = "rust1", since = "1.0.0")]
179180
pub use self::drop::Drop;
181+
#[unstable(feature = "field_projections", issue = "145383")]
182+
pub use self::field_projections::{
183+
DropHusk, HasPlace, PlaceBorrow, PlaceDeref, PlaceDrop, PlaceMove, PlaceRead, PlaceWrapper,
184+
PlaceWrite,
185+
};
180186
#[stable(feature = "rust1", since = "1.0.0")]
181187
pub use self::function::{Fn, FnMut, FnOnce};
182188
#[stable(feature = "rust1", since = "1.0.0")]

tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
_3 = copy _1;
1414
StorageLive(_4);
1515
_4 = copy _2;
16-
- _0 = offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable];
16+
- _0 = std::intrinsics::offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable];
1717
+ _0 = Offset(move _3, move _4);
1818
+ goto -> bb1;
1919
}

tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
_3 = copy _1;
1414
StorageLive(_4);
1515
_4 = copy _2;
16-
- _0 = offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable];
16+
- _0 = std::intrinsics::offset::<*const i32, isize>(move _3, move _4) -> [return: bb1, unwind unreachable];
1717
+ _0 = Offset(move _3, move _4);
1818
+ goto -> bb1;
1919
}

0 commit comments

Comments
 (0)