Skip to content

Commit f5cbf5d

Browse files
committed
add lang items for field projections via virtual places
1 parent e8e4541 commit f5cbf5d

9 files changed

Lines changed: 1406 additions & 18 deletions

compiler/rustc_hir/src/lang_items.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,33 @@ language_item_table! {
444444
FieldType, sym::field_type, field_type, Target::AssocTy, GenericRequirement::Exact(0);
445445
FieldOffset, sym::field_offset, field_offset, Target::AssocConst, GenericRequirement::Exact(0);
446446

447+
// Field projections lang-items.
448+
Subplace, sym::subplace, subplace, Target::Trait, GenericRequirement::Exact(0);
449+
SubplaceSource, sym::subplace_source, subplace_source, Target::AssocTy, GenericRequirement::Exact(0);
450+
SubplaceTarget, sym::subplace_target, subplace_target, Target::AssocTy, GenericRequirement::Exact(0);
451+
SubplaceOffset, sym::subplace_offset, subplace_offset, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
452+
Place, sym::place, place, Target::Trait, GenericRequirement::Exact(0);
453+
PlaceTarget, sym::place_target, 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+
PlaceWrapperWrapped, sym::place_wrapper_wrapped, place_wrapper_wrapped, Target::AssocTy, GenericRequirement::Exact(1);
472+
PlaceWrapperWrap, sym::place_wrapper_wrap, place_wrapper_wrap, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1);
473+
447474
// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
448475
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
449476
}

compiler/rustc_span/src/symbol.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ symbols! {
832832
dreg_low8,
833833
dreg_low16,
834834
drop,
835+
drop_husk,
836+
drop_husk_drop_husk,
835837
drop_in_place,
836838
drop_types_in_const,
837839
dropck_eyepatch,
@@ -1514,6 +1516,25 @@ symbols! {
15141516
pin,
15151517
pin_ergonomics,
15161518
pin_v2,
1519+
place,
1520+
place_borrow,
1521+
place_borrow_borrow,
1522+
place_borrow_safety,
1523+
place_deref,
1524+
place_deref_deref,
1525+
place_drop,
1526+
place_drop_drop,
1527+
place_move,
1528+
place_read,
1529+
place_read_read,
1530+
place_read_safety,
1531+
place_target,
1532+
place_wrapper,
1533+
place_wrapper_wrap,
1534+
place_wrapper_wrapped,
1535+
place_write,
1536+
place_write_safety,
1537+
place_write_write,
15171538
platform_intrinsics,
15181539
plugin,
15191540
plugin_registrar,
@@ -1990,6 +2011,10 @@ symbols! {
19902011
sub,
19912012
sub_assign,
19922013
sub_with_overflow,
2014+
subplace,
2015+
subplace_offset,
2016+
subplace_source,
2017+
subplace_target,
19932018
suggestion,
19942019
super_let,
19952020
supertrait_item_shadowing,

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

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, Place, 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)