design/ops/place/place.rs
1//! ## Operations on places
2//!
3//! <details><summary>Birds-eye view of this module</summary>
4//!
5//! Here are all the items defined by this module without any attributes or
6//! other distractions:
7//!
8//! ```ignore
9#![doc = macros::raw_summary!()]
10//! ```
11//!
12//! </details>
13//!
14//! This module provides traits to customize the place operations of Rust.
15//!
16//! ## Places and Place Expressions
17//!
18//! A *place* in Rust is a particular location in memory. Places are represented
19//! by [*place expressions*][ref-place-exprs], which have the following syntax:
20//!
21//! [ref-place-exprs]: https://doc.rust-lang.org/reference/expressions.html#r-expr.place-value.place-expr-kinds
22//!
23//! - `$path`: paths that refer to local variables (also parameters) and
24//! statics,
25//! - `*$place`: dereferencing another place expression,
26//! - `$place[$expr]`: indexing into another place expression,
27//! - `$place.$ident`: accessing a field of another place expression,
28//! - `($place)`: parenthesized place expressions,
29//! - `$value`: an arbitrary expression; it's value is stored in a temporary
30//! place whose lifetime is determined from its context.
31//!
32//! Further reading:
33//! - <https://nadrieril.github.io/blog/2025/12/06/on-places-and-their-magic.html>
34//! - <https://www.ralfj.de/blog/2024/08/14/places.html>
35//!
36//! Place expressions have a direct representation in the form of a
37//! [`PlaceHandle`]. A handle points at a place and is responsible for
38//! performing all available place operations on the represented place.
39//! Any valid place expression is converted into a handle by the compiler. We
40//! represent this conversion with the `handle!` pseudo-macro, explained below.
41//!
42//! The information a handle encodes can be broken into three primary categories:
43//!
44//! - The type of the place the handle refers to.
45//! - Runtime information needed to access the place; usually, a pointer.
46//! - The capabilities of the pointer the handle was derived from.
47//!
48//! For example:
49//!
50//! ```ignore
51//! let a: &mut Struct;
52//! let b: MutHandle<'b, Field> = handle!((*a).field);
53//! ```
54//!
55//! Semantically, we can tell from the type of the handle that this place
56//! expression is derived from a mutable reference, that the place is of type
57//! `Field`, and that the handle has permission to access the place for the
58//! lifetime `'b`.
59//!
60//! The definition of [`MutHandle<'a, T>`](crate::place::MutHandle) itself is
61//! simple: It stores a pointer to the place (the field, in the example above).
62//! It also embeds a `PhantomData<&'a mut T>` to mark the type `T` as invariant.
63//!
64//! To see how a place handle represents capabilities, observe how we turn this
65//! expression back into a mutable reference of the field:
66//!
67//! ```no_run
68//! # use design::{place::*, ops::place::*};
69//! # struct Struct { field: Field }; struct Field;
70//! # let b: MutHandle<Field> = todo!();
71//! # unsafe {
72//! let c: &mut Field = <MutHandle<'_, Field> as BorrowPlace<&mut Field>>::borrow(b);
73//! # }
74//! ```
75//!
76//! If the handle had been derived from a shared reference (`a` was `&Struct`
77//! above), the handle type would instead be `RefHandle<'_, Field>` which does
78//! not implement `BorrowPlace<&mut Field>`. It does implement
79//! `BorrowPlace<&Field>`, so the following code compiles.
80//!
81//! ```no_run
82//! # use design::{place::*, ops::place::*};
83//! # struct Struct { field: Field }; struct Field;
84//! # #[cfg(false)]
85//! let a: &mut Struct;
86//! # #[cfg(false)]
87//! let b: RefHandle<'b, Field> = handle!((*a).field);
88//! # let b: RefHandle<Field> = todo!();
89//! # unsafe {
90//! let c: &Field = <RefHandle<'_, Field> as BorrowPlace<&Field>>::borrow(b);
91//! # }
92//! ```
93//!
94//! ### Converting place expressions into handles
95//!
96//! Any valid place expression is converted into a handle by the compiler. We
97//! give this desugaring as a pseudo[^1]-macro definition:
98//!
99//! [^1]: we use the non-existent macro fragment specifiers of `place` for place
100//! expressions and `member` for struct field names and tuple indices.
101//! Additionally, we require eager expansion of macros, as we use the
102//! output of the `handle!` macro in the input of the `subplace!` macro.
103//!
104//! ```ignore
105//! macro_rules! handle {
106//! ($path:path) => { LocalHandle::new(&raw {const,mut} $path) };
107//!
108//! ($place:place[$expr:expr]) => {
109//! <
110//! typeof($place) as IndexPlace<typeof($expr), _>
111//! >::index(handle!($place), $expr)
112//! };
113//!
114//! (*$place:place) => { DerefPlace::deref_place(handle!($place)) };
115//!
116//! ($place:place.$field:member) => {
117//! let subplace
118//! = subplace!(typeof($place), $field, handle!($place));
119//! ProjectPlace::<typeof(subplace)>::project_place(
120//! handle!($place),
121//! subplace,
122//! )
123//! };
124//!
125//! (($place:place)) => { handle!($place) };
126//!
127//! // value-to-place coercions are turned into temporaries:
128//! ($value:expr) => {{
129//! super let value = $value;
130//! handle!(value)
131//! }};
132//! }
133//! ```
134//!
135//! Links to the types and traits used: [`LocalHandle`], [`IndexPlace`],
136//! [`DerefPlace`], and [`ProjectPlace`].
137//!
138//! [`LocalHandle`]: crate::place::LocalHandle
139//!
140//! The need for a `subplace!` pseudo-macro might seem surprising, but it's
141//! required to support *place wrappers*, which we will cover in the next
142//! section. Without place wrappers, we could simply replace the `subplace!`
143//! invocation with
144//! <code><[field_of!](std::field::field_of)(typeof($place), $field)>::[default](Default::default)()</code>.
145//!
146//! ### Place Wrappers
147//!
148//! Place wrappers are a special kind of place proxy. They "physically contain"
149//! the place they are proxying for. A good example is [`MaybeUninit<T>`]. To
150//! support subplaces of these place wrappers, the [`WrapPlace`] trait exists.
151//! It allows forwarding subplaces to the proxy and changing the subplace access
152//! information. With [`MaybeUninit<T>`], this allows accessing any subplace
153//! under the transformation that its type is wrapped in `MaybeUninit`. So
154//! given `&MaybeUninit<Struct>`, the `field` subplace can be borrowed using `&`
155//! and it has type `&MaybeUninit<Field>`.
156//!
157//! [`MaybeUninit<T>`]: std::mem::MaybeUninit
158//!
159//! ## Place Operation Traits
160//!
161//! Aside from the three basic place operations of [`ReadPlace`],
162//! [`WritePlace`], and [`BorrowPlace`], there are also the following other
163//! operations:
164//!
165//! - [`MovePlace`] -- moving out of a place (looks the same as a read
166//! operation).
167//! - [`IndexPlace`] -- using the index operator on places (`place[idx]`).
168//! - [`DerefPlace`] -- dereferencing a pointer that's in a place (`*place`).
169//! - [`ProjectPlace`] -- accessing a subplace (`place.field`).
170//! - [`DropPlace`] -- dropping the contents of a place (no surface syntax,
171//! emitted by the compiler).
172//! - [`ReadMetadata`] -- TODO (no surface syntax, emitted by the compiler).
173//! - [`ReadVariant`] -- TODO (no surface syntax, emitted by the compiler).
174//! - [`VariantPlace`] -- TODO (no surface syntax, emitted by the compiler).
175//!
176//! The place operations are desugared in a similar manner to place expressions.
177//! In particular, a place operation always operates upon a place expression,
178//! which relies on the desugaring detailed in the previous section. Refer to
179//! the operation traits for their desugaring.
180//!
181//! ## Safety
182//!
183//! All operation functions are `unsafe`, since they have raw pointer arguments
184//! that have safety preconditions. The arguments are raw pointers, because the
185//! values they point to need not be in a valid state (they may be partially
186//! moved out or borrowed).
187//!
188//! The safety requirements for the operation functions have not been figured
189//! out at this point in time. Since we expect several changes to the design, we
190//! do not want to commit to writing down good safety documentation before
191//! having finished the design.
192//!
193//! What is clear at the moment is that the safety requirements will heavily
194//! interact with the borrow checker. It will ensure that simultaneous place
195//! operations on the same value are allowed, since they either affect disjoint
196//! subplaces, or because they both only require shared access. For example:
197//! - reading `ptr.field.subfield` and borrowing `ptr.field` with `&T` are
198//! allowed to happen at the same time,
199//! - writing `ptr.field` and borrowing `ptr.field.subfield` at the same time is
200//! not allowed.
201//!
202//! The safety of using the place operations via the operators will depend on
203//! the value of the `SAFE` constant in the operation traits. At the moment we
204//! will only permit a literal value of `true` or `false` in implementations. It
205//! will dictate if people have to write for example `unsafe { &*ptr }` or if
206//! `*ptr` is allowed. It should be set to `true` when the borrow checker's
207//! guarantees of either disjoint subplaces or "all concurrent operations are
208//! shared" are enough to calling the operations' function correctly. If there
209//! are additional requirements, such as "ptr is valid", then `SAFE` should be
210//! set to `false`. For example, `&mut T` will have `SAFE = true` in
211//! [`ReadPlace`], but `NonNull<T>` will set it to `false`.
212//!
213//! ### Handle Validity
214//!
215//! TODO
216
217#[macros::summary(skip)]
218use crate::{
219 ops::place::borrowck::{
220 AccessKind,
221 Timing,
222 },
223 place::{
224 HasVariant,
225 Matchable,
226 Subplace,
227 VariantType,
228 },
229 ptr::Metadata,
230};
231
232#[macros::summary(skip)]
233pub mod borrowck;
234
235/// A type proxying for a place.
236///
237/// A value of this type represents a specific place. The operations that are
238/// available on that place are controlled by which *place operation traits* are
239/// implemented on the handle of that place, which is [`CreateHandle::Handle`].
240pub trait PlaceProxy {
241 type Target: ?Sized;
242}
243
244/// TODO: Defines creation of handles.
245///
246/// A handle to the represented place can be obtained from a value of this type
247/// by calling <code>Self::[handle_from_raw]</code>.
248///
249/// The timing of the access permissions of [`Self::handle_from_raw`] is
250/// `ProxyTiming`.
251///
252/// The <code>Self::[ACCESS]</code> constant specifies what type of permission
253/// is required for creating a handle this way. The `ProxyTiming` argument
254/// specifies for how long that permission must be granted; it must be one of
255/// the types in the [`borrowck`] module. Any compiler-generated handle
256/// creations automatically honor these requirements via the borrow checker.
257///
258/// [`borrowck`]: crate::ops::place::borrowck
259/// [ACCESS]: Self::ACCESS
260/// [handle_from_raw]: Self::handle_from_raw
261pub unsafe trait CreateHandle<ProxyTiming: Timing>: PlaceProxy {
262 /// The *handle* that's used for operating on the represented place.
263 ///
264 /// This type controls which place operations are available on the
265 /// represented place. For example, if this implements [`ReadPlace`], then
266 /// writing `*self` is allowed and yields a value of type
267 /// <code>Self::[Handle]::[Target](PlaceHandle::Target)</code> (where `self:
268 /// Self`).
269 ///
270 ///
271 /// [Handle]: Self::Handle
272 /// [ACCESS]: Self::ACCESS
273 /// [handle_from_raw]: Self::handle_from_raw
274 type Handle: PlaceHandle<Target = Self::Target>;
275
276 /// The access permissions required by [`Self::handle_from_raw`].
277 const ACCESS: AccessKind;
278
279 /// Create a handle to the pointee of the raw pointer.
280 ///
281 /// # Safety
282 ///
283 /// - `this` must be a valid pointer for as long as the return value lives,
284 /// - `*this` must be [handle-valid] with permissions [`Self::ACCESS`] for
285 /// `ProxyTiming`.
286 ///
287 /// [handle-valid]: self#handle-validity
288 unsafe fn handle_from_raw(this: *const Self) -> Self::Handle;
289}
290
291/// A *handle* to a place.
292///
293/// All place operations are carried out by handles. Whether a place operation
294/// is available depends on the handle type implementing the respective [*place
295/// operation trait*][self#place-operation-traits].
296///
297/// Place handles are not user-facing. Instead, they and the use of their
298/// operations are emitted by the compiler as part of desugaring [*place
299/// expressions*](self#places-and-place-expressions) and place operations.
300pub trait PlaceHandle: Sized {
301 /// The type that's stored in the place.
302 type Target: ?Sized;
303}
304
305/// `let _ = place;` -- Read from a place.
306///
307/// Reading from a place doesn't have any special syntax, instead a read can
308/// happens in many places. This occurs precisely when a place expression is
309/// used in a *value context[^1].* For example:
310///
311/// - `let _ = place;`
312/// - `match place { /* ... */ }`
313/// - `function(place)`
314///
315/// When a place expression is being read, its handle must implement this trait.
316/// Additionally, the type stored in the place must be [`Copy`], or the handle
317/// must also implement [`MovePlace`]. Otherwise a compiler error will be
318/// emitted that the value cannot be moved out.
319///
320/// [`Self::Target`]: PlaceHandle::Target
321/// [^1]: <https://doc.rust-lang.org/nightly/reference/expressions.html#r-expr.move>
322pub unsafe trait ReadPlace: PlaceHandle {
323 /// The access permissions to the place required by [`Self::read_place`].
324 const ACCESS: AccessKind;
325 /// Whether [`Self::read_place`] is safe when [`Self::ACCESS`] is honored.
326 ///
327 /// This constant controls whether the compiler will require writing an
328 /// `unsafe` block around reading from a place that uses this handle.
329 const SAFE: bool;
330
331 /// Read from the place.
332 ///
333 /// # Safety
334 ///
335 /// This handle must have [`Self::ACCESS`] permissions for the duration of
336 /// this method call.
337 unsafe fn read_place(self) -> Self::Target;
338}
339
340/// `let _ = place;` -- Move out of a place.
341///
342/// When reading from a place, the type of the contents of the place must
343/// implement [`Copy`], or the handle must implement this trait. This trait
344/// allows moving out of the place, leaving it in a partially initialized state.
345///
346/// When implementing this trait, [`DropPlace`] should almost always also be
347/// implemented, since otherwise dropping a partially moved-out proxy is not
348/// permitted. Additionally, the proxy should implement [`DropHusk`] for the
349/// same reason.
350///
351/// The actual move-out operation is performed by reading the place
352/// ([`ReadPlace::read_place`]) and then changing the borrow checker state of
353/// this place to uninitialized.
354pub unsafe trait MovePlace: ReadPlace {}
355
356/// `place = value;` -- Write to a place.
357///
358/// Writing to a place is done by writing the place on the left hand side of an
359/// assignment expression.
360pub unsafe trait WritePlace: PlaceHandle {
361 /// The access permissions to the place required by [`Self::write_place`].
362 const ACCESS: AccessKind;
363 /// Whether [`Self::write_place`] is safe when [`Self::ACCESS`] is honored.
364 ///
365 /// This constant controls whether the compiler will require writing an
366 /// `unsafe` block around writing to a place that uses this handle.
367 const SAFE: bool;
368
369 /// Write to the place.
370 ///
371 /// # Safety
372 ///
373 /// This handle must have [`Self::ACCESS`] permissions for the duration of
374 /// this method call.
375 unsafe fn write_place(self, value: Self::Target);
376}
377
378/// `&place`/`@place` -- Borrow a place as `Output`.
379///
380/// Borrowing a place creates a pointer to the place. This operation is generic
381/// over the resulting pointer type and borrowing the same place with many
382/// different pointer types is supported.
383///
384/// There are a few ways to spell borrowing a place:
385///
386/// - `&place` and `&mut place` --- resulting in `Output = &_` and `Output = &mut
387/// _` respectively,
388/// - `&raw const place` and `&raw mut place` --- `Output = *const _` and
389/// `Output = *mut _`
390/// - `@place` and `@<$ty> place` --- `Output = _` and `Output = $ty`
391///
392/// All of these are desugared to
393/// `BorrowPlace::<Output>::borrow(handle!($place))`. Where `handle!` is
394/// explained in the [section on place
395/// expressions](self#places-and-place-expressions)
396pub unsafe trait BorrowPlace<Output>: PlaceHandle {
397 /// The access permissions to the place required by [`Self::borrow`].
398 const ACCESS: AccessKind;
399 /// The timing of the access permissions of [`Self::borrow`].
400 type Timing: Timing;
401 /// Whether [`Self::borrow`] is safe when [`Self::ACCESS`] is honored for
402 /// [`Self::Timing`].
403 ///
404 /// This constant controls whether the compiler will require writing an
405 /// `unsafe` block around borrowing a place that uses this handle.
406 const SAFE: bool;
407
408 /// Borrow the place using `Output`.
409 ///
410 /// # Safety
411 ///
412 /// This handle must have [`Self::ACCESS`] permissions for the duration of
413 /// [`Self::Timing`].
414 unsafe fn borrow(self) -> Output;
415}
416
417/// `place[idx]` -- Enable indexing into `Self`.
418///
419/// Indexing is only supported for certain places: namely those handles `H`,
420/// for which `Self` implements [`IndexPlace<Idx, H, _, _>`].
421///
422/// In a way, this trait is a generic version of [`PlaceProxy`], since indexing
423/// allows changing the type based on the type of the index.
424pub trait Indexable<Idx> {
425 /// The type of the place expression `self[idx]`.
426 type Element: ?Sized;
427}
428
429/// `place[idx]` -- Index into `Self` via the handle `H`.
430///
431/// The same way that [`Indexable`] is the generic version of [`PlaceProxy`],
432/// this trait is the generic version of [`DerefPlace`].
433///
434/// Indexing -- like dereferencing -- also performs two accesses from the
435/// borrow-checker's perspective:
436///
437/// - the place that comes out of the index operation (`place[idx]`), and
438/// - the place that is being indexed into (`place`).
439///
440/// For this reason, there are two [`AccessKind`] constants and two [`Timing`]
441/// generics, see the documentation of [`DerefPlace`] for more information about
442/// them.
443pub unsafe trait IndexPlace<Idx, H, PointeeTiming, PointerTiming>:
444 Indexable<Idx>
445where
446 H: PlaceHandle<Target = Self>,
447 PointeeTiming: Timing,
448 PointerTiming: Timing,
449{
450 /// The type of handles to indexed elements.
451 type ElementHandle: PlaceHandle<Target = Self::Element>;
452
453 /// The access permissions to the contents of the place handled by `Self`
454 /// required by [`Self::index`].
455 const POINTEE_ACCESS: AccessKind;
456 /// The access permissions to the place handled by `Self` required by
457 /// [`Self::index`].
458 const POINTER_ACCESS: AccessKind;
459 /// Whether [`Self::index`] is safe when [`Self::POINTEE_ACCESS`] and
460 /// [`Self::POINTER_ACCESS`] are honored for `PointeeTiming` and
461 /// `PointerTiming` respectively.
462 ///
463 /// This constant controls whether the compiler will require writing an
464 /// `unsafe` block around indexing into a place that uses the `H` handle.
465 const SAFE: bool;
466
467 /// Indexes into the value stored at `H`.
468 fn index(handle: H, idx: Idx) -> Self::ElementHandle;
469}
470
471/// `*place` -- Dereference the contents of a place.
472///
473/// Dereferencing from a borrow-checker perspective requires access to two
474/// places:
475///
476/// - the place that comes out of the dereference operation (`*place`), and
477/// - the place that's being dereferenced (`place`).
478///
479/// For this reason, the dereference operation has two associated constants of
480/// type [`AccessKind`] that specify the access permissions required for the two
481/// accesses and two [`Timing`] generics[^1] called `PointeeTiming` and
482/// `PointerTiming`.
483///
484/// Given a pointer `ptr`, the place that comes out of the dereference is `*ptr`
485/// and the place that is being dereferenced is `ptr`. The `PointerTiming`
486/// generic and [`Self::POINTER_ACCESS`] constant control how the borrow checker
487/// treats the access to `ptr`, while `PointeeTiming` and
488/// [`Self::POINTEE_ACCESS`] specify the kind of access to `*ptr`.
489///
490/// Utilizing this fact, one can encode that a pointer can be invalidated
491/// without invalidating pointers that were derived from dereferenced pointers.
492/// This is the case for mutable references:
493///
494/// ```ignore
495/// fn overwrite_nested<'a>(ptr: &mut &'a mut Struct, make: impl FnOnce() -> &'a mut Struct) {
496/// let a: &'a mut Field = &mut (**ptr).field;
497/// *ptr = make();
498/// let b: &'a mut Field = &mut (**ptr).field;
499///
500/// mem::swap(a, b); // can use both `a` and `b`!
501/// }
502/// ```
503///
504/// In this case, dereferencing `&mut` has [`Instant`](borrowck::Instant) as the
505/// `PointerTiming`, which results in never invalidating derived pointers when
506/// the original is used for something else.
507///
508/// [^1]: They can't be associated types, because the timing [`Lifetime<'a>`]
509/// has a lifetime. If they were associated types, one could only use
510/// [`Lifetime<'a>`] if the handle also had that same lifetime. Because
511/// handles generally want to allow shortening lifetimes, the timing needs
512/// to introduce a fresh lifetime.
513///
514/// [`Lifetime<'a>`]: borrowck::Lifetime
515pub unsafe trait DerefPlace<PointeeTiming, PointerTiming>:
516 PlaceHandle
517where
518 Self::Target: CreateHandle<PointeeTiming>,
519 PointeeTiming: Timing,
520 PointerTiming: Timing,
521{
522 /// The access permissions to the contents of the place handled by `Self`
523 /// required by [`Self::deref_place`].
524 const POINTEE_ACCESS: AccessKind;
525 /// The access permissions to the place handled by `Self` required by
526 /// [`Self::deref_place`].
527 const POINTER_ACCESS: AccessKind;
528 /// Whether [`Self::deref_place`] is safe when [`Self::POINTEE_ACCESS`] and
529 /// [`Self::POINTER_ACCESS`] are honored for `PointeeTiming` and
530 /// `PointerTiming` respectively.
531 ///
532 /// This constant controls whether the compiler will require writing an
533 /// `unsafe` block around dereferencing a place that uses the this handle.
534 const SAFE: bool;
535
536 unsafe fn deref_place(
537 self,
538 ) -> <Self::Target as CreateHandle<PointeeTiming>>::Handle;
539}
540
541/// `place.field` -- Project a handle to a subplace.
542pub unsafe trait ProjectPlace<S>: PlaceHandle
543where
544 S: Subplace<Source = Self::Target>,
545{
546 type Projected: PlaceHandle<Target = S::Target>;
547
548 unsafe fn project_place(self, subplace: S) -> Self::Projected;
549}
550
551/// Wrap a place, exposing some of its subplaces.
552pub trait PlaceWrapper {
553 type Inner: ?Sized;
554}
555
556/// `place.field` -- Expose a modified subplace of the wrapped place.
557pub unsafe trait WrapPlace<S>: PlaceWrapper
558where
559 S: Subplace<Source = Self::Inner>,
560{
561 type Wrapped: Subplace<Source = Self>;
562
563 fn wrap(subplace: S) -> Self::Wrapped;
564}
565
566/// Drop the contents of a place.
567///
568/// This operation should only drop the value at the place and not invalidate
569/// the proxy itself. A new value might be moved back in later with
570/// [`WritePlace`].
571///
572/// Calls to [`Self::drop_place`] are emitted by the compiler as part of
573/// dropping a [`PlaceProxy`] that's partially moved out.
574pub unsafe trait DropPlace: PlaceHandle {
575 unsafe fn drop_place(self);
576}
577
578/// Destroy a [`PlaceProxy`] where its contents have been moved out/dropped.
579///
580/// This is essentially like [`Drop`], but supports the situation where the
581/// value stored in the place represented by `Self` have been moved out,
582/// dropped, or never initialized to begin with.
583///
584/// The borrow checker tracks the initialization state of each (sub)place. When
585/// a [`PlaceProxy`] supports moving values out (i.e. when its handle implements
586/// [`MovePlace`]), then after moving out the entire value, the allocation might
587/// still be live. Since the value is no longer populated, calling
588/// [`Drop::drop`] as normal would result in using a moved-out value, which can
589/// result in a double-free.
590///
591/// Instead, this trait is combined with [`DropPlace`], which the compiler uses
592/// to drop any not-moved-out subplaces and then drops the allocation (or any
593/// other data that the proxy had) through this trait.
594pub unsafe trait DropHusk: PlaceProxy {
595 /// Destroy the proxy associated with the place of `this`.
596 unsafe fn drop_husk(this: *mut Self);
597}
598
599/// Obtain the metadata of the contents of a place.
600pub unsafe trait ReadMetadata: PlaceHandle {
601 fn metadata(self) -> Metadata<Self::Target>;
602}
603
604/// Obtain the discriminant of the contents of a place.
605pub unsafe trait ReadVariant: PlaceHandle
606where
607 Self::Target: Matchable,
608{
609 unsafe fn read_variant(self) -> &'static str;
610}
611
612/// Cast a handle to a place to a subtype.
613pub unsafe trait VariantPlace<const VARIANT: &'static str>:
614 ReadVariant
615where
616 Self::Target: Matchable,
617 Self::Target: HasVariant<VARIANT>,
618{
619 type ToVariant: PlaceHandle<Target = VariantType<Self::Target, VARIANT>>;
620
621 unsafe fn cast(self) -> Self::ToVariant;
622}