PartialBorrow

Derive Macro PartialBorrow 

Source
#[derive(PartialBorrow)]
{
    // Attributes available to this derive:
    #[partial_borrow]
}
Expand description

Derive partial borrowing for a struct.

§Invocation details

Must be applied to a sized braced struct (“Struct”, below) (By “braced struct” we mean what the Reference calls a StructStruct.)

The invocation scope must have imported the partial_borrow crate, under that name.

Takes the additional attribute #[partial_borrow(...)] where ... may be some of the following parameters:

  • Debug: Generates a Debug impl for the partial struct (and impls for its field accessor proxies). Inaccessible fields are debug printed as _.

  • partial="Partial": The permission-parameterised partially borrowed struct will be called Partial instead of Struct__Partial.

  • module="Module": The module containing field definitions will be called Module instead of Struct__.

  • suffix="identchars": identchars will be used instead of __ in generated identifiers, including local variables in generated functions, added type and lifetime parameters, and the default values of partial and module.

    See Injected names, below.

  • imported_for_test_unsafe: Indicates that the invocation scope has use partial_borrow::imports::*. The generated code will just say foo rather than partial_borrow::imports:foo. This is useful for testing and for review by humans.

    Safety! For soundness, the derived code’s uses of now-unqualified names must always refer to the traits and types in partial_borrow::imports. This is difficult to ensure in nontrivial programs. This feature is provided for maintenance, testing, diagnostics, etc.

§Generated items

This derive macro introduces two names and many trait implementations into the invoking scope. Both the named items have the same visibility as Struct.

§Partially borrowed struct view

struct Struct__Partial<...> { ... }

Struct__Partial is generic over all the same things as Struct, but additionally, just after the lifetimes, it has additional type parameters: one P__field for each field named field.

You can never have an owned Struct__Partial, just borrows of it. Such a borrow represents a borrow of each individual field, according to the permission type parameter P__field (which will be one of Mut Const No).

Fields with permission Const are only immutably accessible, even via an &mut Struct_Partial. Fields with permission Mut are mutably accessible, but of course only if you have an &mut Struct_Partial. Fields with permission No are inaccessible.

Each field of the borrow is a smart pointer Struct__::F_field which (when allowed) dereferences to the actual field. So accessing fields other than by method call typically involves an additional *.

§impls

  • Downgrade and AsRef and AsMut, to make references to partial structs from more powerful references.

  • SplitOff, SplitInto and [From] to divide references into mutually-compatible partial struct views.

  • If the Debug parameter was specified, Debug for Struct_Partial and for field accessors Struct__::F__field.

  • Deref impl which allows any complete, but perhaps partially-immutable, struct view, to deref back to an &Struct. (I.e., this works for any partial view without any No permissions, only Const and Mut ones.)

  • Deref and DerefMut impls for the field accessors.

Note that the downgrade and splitting traits are implemented for &Struct and &mut Struct as well: you make partial struct view reference(s) from a complete struct reference the same way you do from a partial struct reference.

§Implementation of other traits for partial structs

Traits which do not understand partial structs are generally not implemented (or implementable) for them. Trait methods that only take &self can be called via the Deref if all of the fields are at least Const-accessible.

In principle it would be possible to provide a facility to apply #[derive] attributes to the generated struct. But it would not be possible to pass any attributes (on the struct or any fields), because the attributes might be macros which would alter the generated Struct__Partial, whose shape is important for the soundness.

Trait and inherent impls on partial structs are fine and can be useful.

§Module

mod Struct__ {
    struct F_field<Permission, FieldType, Struct> { ... }
}

This contains helper items. Notably, the F_field type for each field field, which dereferences to the value. Like Struct__Partial, it is not possible to obtain an owned field accessor struct, just references.

§Injected names

Many of the impls require additional generic parameters, all of which are generated as X__ or X__field or 'x__ for some X or x.

Here is a full list of the generic parameters injected anywhere where they might clash with your names: 'r__ P__ S__ T__ N__ R__ P__field R__field S__field. But: note that additions to this list will not be considered a semver break.

All this will only trouble you if you derive PartialBrorrow on a struct which has other generic parameters containing __. If any injected names might clash with other generics for your struct, use the suffix paramrter to change __ to something else.

(All this is in addition to the generated items Struct__Partial Struct__, documented above.)