Partially borrow a struct. Multiple simultaenous mutable partial borrows are possible, so long as each field is only mutably accessible via (at most) one of them.

Primary reference documentation and entrypoints

Motivation

Before ```

use std::ops::*;

type GameState=(); type IPieces=(); type IOccults=();

#[derive(Default)]

struct Instance { gs: GameState, ipieces: IPieces, ioccults: IOccults, /.. ../ };

fn some_operation(gs: &mut GameState, // Several pointers, ipieces: &IPieces, // all to fields of struct Instance. ioccults: &IOccults, // We only want to pass partial mut.

_: RangeTo) { }

let _ =

              .. ..

;

let mut instance = Instance::default();

some_operation(&mut instance.gs, // Much typing to pass each field. &instance.ipieces, &instance.ioccults, .. ..

);

After

use std::ops::*;

use partial_borrow::prelude::*;

type GameState=(); type IPieces=(); type IOccults=();

#[derive(PartialBorrow,Default)]

struct Instance { gs: GameState, ipieces: IPieces, ioccults: IOccults };

fn some_operation(// One pointer. Need only list fields to be mut, here. g: &mut partial!(Instance mut gs),

_: RangeTo) { }

let _ =

            .. ..

;

let mut instance = Instance::default();

someoperation(instance.asmut(), .. .. // Type one parameter at the call site.

);

```

Example

``` use partialborrow::prelude::*; use partialborrow::SplitOff;

[derive(Debug,PartialBorrow,Default)]

[partial_borrow(Debug)]

pub struct Garden { trees: usize, gate_open: bool, }

// This can't be an inherent method but it could be an extension // trait method using a crate like easy_ext. pub fn operategate(g: &mut partial!(Garden mut gateopen), open: bool) { *g.gateopen = open; eprintln!("operategate, {:?}", g); }

[derive(Debug)]

struct TreeAdmirer<'g> { g: &'g partial!(Garden const trees, !*), } impl TreeAdmirer<'> { fn admire(&self) { eprintln!("I see {} trees {:?}", *self.g.trees, self); // XX eprintln!("gate open? {}", *self.g.gateopen); // ^ error: type F_gate_open<No, bool, Garden> cannot be dereferenced } }

let mut garden = Garden::default(); operategate(garden.asmut(), true); garden.trees += 1; let (forgate, rest) = SplitOff::splitoffmut(&mut garden); let guest = TreeAdmirer { g: rest.asref() }; guest.admire(); operategate(forgate, false); guest.admire(); Output text operategate, GardenPartial { trees: 0, gateopen: true } I see 1 trees TreeAdmirer { g: GardenPartial { trees: 1, gateopen: _ } } operategate, GardenPartial { trees: 1, gateopen: false } I see 1 trees TreeAdmirer { g: GardenPartial { trees: 1, gateopen: _ } } ```

Method example with easy_ext

```

#[derive(Default,PartialBorrow)]

pub struct Garden { gate_open: bool }

use partialborrow::prelude::*; use easyext::ext;

[ext]

impl partial!(Garden mut gateopen) { pub fn operategate(&mut self, open: bool) { /.../ } }

let mut garden = Garden::default(); garden.asmut().operategate(true); ```

Safety

The provided API is supposed to be safe and sound.

The implementation involves an awful lot of proc-macro-generated unsafe. There are tests with miri and a correctness argument in the form of extensive hand-written annotations to an autogenerated output. There has not been any independent review, and no attempt at validation using formal methods.

The macro-generated code refers extensively to items from this crate, under its canonical name partial_borrow. Using that name for something else is in theory unsound, although it is highly unlikely that the proc-macro output would compile if that name somehow referred to an unrelated crate, so this does not seem to be a practical concern.