# Crate partial_ref[−][src]

## Expand description

Type checked partial references.

This crate provides type checked partial references for rust. Type checked partial references are one solution to solve interprocedural borrowing conflicts.

# Tutorial

With this crate it is possible to declare typed parts (using the `part`

macro) and to assign
struct fields to these parts (by deriving `PartialRefTarget`

).

use partial_ref::{part, PartialRefTarget}; part!(pub Neighbors: Vec<Vec<usize>>); part!(pub Colors: Vec<usize>); part!(pub Weights: Vec<f32>); #[derive(PartialRefTarget, Default)] pub struct Graph { #[part(Neighbors)] pub neighbors: Vec<Vec<usize>>, #[part(Colors)] pub colors: Vec<usize>, #[part(Weights)] pub weights: Vec<f32>, }

It is then possible to convert a reference to a value using the `IntoPartialRef`

and
`IntoPartialRefMut`

traits, which are derived alongside PartialRefTarget. Note that a mutable
partial reference must itself be mutable for mutable access.

use partial_ref::IntoPartialRefMut; let mut g = Graph::default(); let mut g_ref = g.into_partial_ref_mut();

You can access parts using the `part`

and `part_mut`

methods.

use partial_ref::PartialRef; g_ref.part_mut(Colors).extend(&[0, 1, 0]); g_ref.part_mut(Weights).extend(&[0.25, 0.5, 0.75]); g_ref.part_mut(Neighbors).push(vec![1, 2]); g_ref.part_mut(Neighbors).push(vec![0, 2]); g_ref.part_mut(Neighbors).push(vec![0, 1]); assert_eq!(g_ref.part(Colors).len(), g_ref.part(Neighbors).len()); assert_eq!(g_ref.part(Colors).len(), g_ref.part(Weights).len());

We can now write a function that takes parts of a reference. The type of such a partial
reference can be written using the `partial`

macro, which expands to a combination of `Mut`

,
`Const`

and `Ref`

. Again the parameter `g`

here must be mutable to allow mutable access to
the referenced value. To call such a function we use the `borrow`

method,
which will re-borrow just the required parts.

use partial_ref::partial; pub fn add_color_to_weight( mut g: partial!(Graph, mut Weights, Colors), index: usize, ) { g.part_mut(Weights)[index] += g.part(Colors)[index] as f32; } add_color_to_weight(g_ref.borrow(), 1); assert_eq!(g_ref.part(Weights)[1], 1.5);

So far everything could have been written using plain built-in references. This changes as soon as we want to iterate over the neighbors while invoking our function. Usually we couldn’t pass a mutable reference to the graph while holding the iterator over the neighbors.

This can be easily done using partial references which support splitting. Splitting means
turning a single reference into two references where each has a subset of parts, so that each
mutably referenced part belongs only to a single reference. This is done by the
`split_borrow`

and `split_part`

methods.

let (neighbors, mut g_ref) = g_ref.split_part_mut(Neighbors); let (colors, mut g_ref) = g_ref.split_part(Colors); for (edges, &color) in neighbors.iter_mut().zip(colors.iter()) { edges.retain(|&neighbor| colors[neighbor] != color); for &neighbor in edges.iter() { add_color_to_weight(g_ref.borrow(), neighbor); } }

This covers the basic functionality of this library. Beyond that this library also supports:

- Partial references to nested structs using
`Nested`

and`nested_part`

. - Generic functions with bounds on available parts using
`HasPart`

.

# Notes

Some documented items are marked with *(internal)*. Typical code using this library doesn’t
explicitly refer to them. Nevertheless they often appear in error messages and are thus part of
this documentation. These items also have to be public for the inference driven meta programming
to work. Code that is generic over parts of partial references might also need them.

Many traits in this crate are marked as unsafe without documenting any requirements for implementations. This does not mean they are safe to implement, but rather means that they are not intended to be implemented outside of this library. Feel free to file an issue if you have a good reason to implement them so the requirements can be documented.

## Macros

Expands `A | B | ... | Z`

to `Nested<...Nested<A, B>, ..., Z>`

Declares a [`Part`

].

Concise syntax for partial reference types.

Helper macro for splitting a partial reference.

## Structs

Type of an abstract part.

A constant (immutable) part of a partial reference.

Type of a part that corresponds to a struct field.

*(internal)* Select the first part.

*(internal)* Skip the first part.

*(internal)* Split the first part.

A mutable part of a partial reference.

A nested part.

An empty partial reference borrowing no parts.

*(internal)* Construct a subset index from a part index and another subset index.

*(internal)* Index for the empty subset.

## Traits

*(internal)* Check whether a part is nested inside another part.

Implemented when a reference target has a part.

*(internal)* Asserts that the parts of the partial reference `Reference`

are a subset of the
parts of the partial reference having this trait.

Helper trait to associate the target type with a `PartialRef`

without needing a lifetime.

Construction of partial references.

Construction of partial references from mutable references.

Marker types for a part of a type.

Helper trait to strip lifetimes from a part.

Type of a part, determines what can be done with a part.

A partial reference.

A type that can be the target of partial references.

*(internal)* Extracts the constant part `PluckedPart`

at position `Index`

from the partial
reference having this trait, leaving `Self::Remainder`

.

*(internal)* Extracts the mutable part `PluckedPart`

at position `Index`

from the partial
reference having this trait, leaving `Self::Remainder`

.

*(internal)* Split a part into nested parts.

## Derive Macros

Derives instances of PartialRefTarget and associated traits.