Skip to content

Instantly share code, notes, and snippets.

@djdisodo
Last active January 20, 2021 22:14
Show Gist options
  • Select an option

  • Save djdisodo/1b0bd8d8ad75abbf9af4654a431017c1 to your computer and use it in GitHub Desktop.

Select an option

Save djdisodo/1b0bd8d8ad75abbf9af4654a431017c1 to your computer and use it in GitHub Desktop.

field

field is is interface that represents field of struct

struct Foo {
    x: usize,
    y: usize
}

there's a field x, y in Foo so Foo::x and Foo::y is defined field

field can be accessed like this

fn field1() {
    let foo = Foo {
        x: 42,
        y: 39,
    };
    
    assert_eq!(
        foo.(Foo::x), //and the value of Foo::x can be accessed with Foo
        foo.x //in short
    );
}

field can be field of field of field of .......

struct Bar {
    foo: Foo,
}

so Bar::foo.x and Bar::foo.y is field of Bar

fn field_of_field {
    let bar = Bar {
        foo: Foo {
            x: 1,
            y: 0
        }
    };
    assert_eq!(1, bar.(Bar::foo.x));
    assert_eq!(bar.(Bar::foo).x, bar.(Bar::foo.x));
    assert_eq!(bar.foo.x, bar.(Bar::foo.x));
}

borrows

borrows is a set of field to borrow can be declared using borrows keyword borrows can have public visibility putting borrows in declaration of borrows will flatten it so Foo::{ .. } and Foo::{ Foo::{ .. } } is same

pub borrows borrows1 = Foo::{
    //you can put mutability
    mut x,
    y
}

remaining fields with ..

this will borrow x as immutable and others as mutable

pub borrows negative_borrow1 = Foo::{
    x,
    mut ..
}

negative borrow

this will borrow others except x

pub borrows negative_borrow1 = Foo::{
    !x,
    ..
}

borrowing field of field

this will borrow foo.x

pub borrows borrow3 = Bar::{
    foo.{
        x
    }
}

in short

pub borrows borrow3 = Bar::{
    foo.x
}

examples

//this will borrow Bar::foo with full mutability
pub borrows borrows2 = Bar::{
    mut foo
}

//this will borrow Bar::foo as immutable and borrow Bar::foo.x as mutable
pub borrows borrow3 = Bar::{
    foo.{
        mut x,
        ..
    }
}

//this will borrow Bar::foo as mutable except Bar::foo.x(immutable)
pub borrows borrow4 = Bar::{
    foo.{
        x,
        mut ..
    }
}

pub borrows borrow5 = Foo::{
    mut x,
    ..
}

//this will borrow Bar::foo as immutable and borrow Bar::foo.x as mutable
pub borrows borrow6 = Bar::{
    foo.{ borrow5 }
}

borrowing

borrows used in partial borrow you don't need to do this as current borrow checker automatically implements partial borrow in this case

fn borrows_use() {
    let foo = Foo {
        x: 42,
        y: 39
    };
    
    let foo_part1 = &foo.{ x }; //borrow only x
    //using foo_part1.y will cause borrow check error
    
    let foo_part2: &Foo::{ y } = &foo; //borrow only y
    //using foo_part2.x will cause borrow check error
}

field and borrows in impl block

impl Foo {
...

this example makes private field Foo::x accessible out of the module with foo.x_another field can have public visibility field can be declared with field keyword declared name should not conlfict with field name in Foo

...
    pub field x_another = Self::x;
...

you can borrow all fields of Foo like this

...
    fn field2(&self.{ .. }) {
        self.field3(); //you can borrow all fields of Foo so you can call field3
        self.field4(); //you can borrow Foo::x so you can call field4
    }
...

borrowing all fields can be simplified

...
    fn field3(&self) {
    
    }
...

borrow only Foo::x

...
    fn field4(&self.{ x }) {
        field6(self) //you can borrow Foo::x so you can call field6
    }
...

borrowing fields in typed param

...
    fn field5(foo: &Foo::{ x }) {
        //foo.field5() //you can't call field5 because you can't borrow { !x, .. } which is { Foo::y }
    }
...

borrow except Foo::x

...
    fn field6(&self.{ !x, .. }) {
        
    }
}

field and borrows in impl block

trait Baz {
...

you can declare field in trait block it needs to be implemented when struct implements the trait

...
    field baz_x: usize;
...

borrow all fields of Self

...
    fn field7(&self.{ .. }) -> usize {
        self.baz_x //declared trait can be used here
    }
...

borrow all fields of Baz so it's parital borrow

...
    fn field8(&self.{ Bar::{ .. } }) -> usize{
        self.baz_x
    }
...

you can declare borrows in trait block like in this case, if you don't initialize it it will need to be implemented when implementing trait

...
    borrows f: Self;
...

you can add required borrows to Self::f when implementing Baz::field9

...
    fn field9(&self.{ Self::f }) -> usize;
...
you can borrowed `Self::f` so you can call field9
...
    fn field10(&self.{ bar_x, Self::f }) {
        self.field9();
    }
...
...
    fn field11(&self.{ Self::f }) -> usize;
}

implementing trait with field and borrows

impl Baz for Foo {
...

if Foo already has field with same name this can be accessed like foo.(Baz::field_name)

...
    field baz_x: usize = Self::x;
...

implementing borrows

...
    borrows f = Self::{ y, x }
...

Foo::f has Foo::y so you can access Foo::y

...
    fn field9(&self.{ Self::f }) -> usize {
        self.y //Foo::f has Foo::y so you can access Foo::y
    }
...

you can borrow less than declared in trait

...
    fn field11(&self.{ y }) -> usize {
        self.y
    }
}
fn field13() {
    let foo = Foo {
        x: 42,
        y: 39,
    };
    
    assert_eq!(
        foo.(Baz::bar_x),
        foo.(Foo::bar_x)
    );
    
    assert_eq!(
        foo.(Baz::bar_x),
        foo.bar_x
    );
    
    assert_eq!(
        foo.field8(),
        foo.y
    );
    
    assert_eq!(
        foo.field8(),
        foo.field9()
    );
}

example usage

trait DerefField {
   type FieldType;
   field deref_field: Target;
}

impl<T: DerefField> Deref for DerefField {
    type Target = Self::FieldType;
    fn deref(&self { deref_field }) -> &Self::Target {
        &self.deref_field
    }
}

struct Example<T> {
    value: T
}

impl<T> DerefField<T> for Example<T> {
    field deref_field = self.value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment