# pre-RFC: "field" as an item and "borrows"

**URL:** <https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886>\
**Category:** language design\
**Created:** [January 22, 2021, 6:44pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886 "2021-01-22T18:44:31Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![djdisodo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djdisodo/32/7665_2.png) [@djdisodo](https://internals.rust-lang.org/u/djdisodo)\
**Post date:** [January 22, 2021, 6:44pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/1 "2021-01-22T18:44:32Z")

</div>

as I'm not a native english speaker plz tell me if there is any part that is difficult to read and understand

# Summary

`field` is an item that represents field in `struct`.

`borrows` is a set of `field` that supports borrowing.

I'm not convinced about name `borrows`. maybe there will be a better name for it plz suggest me

# Motivation

## field as item

this allows traits to have field which needs to be implemented when implementing trait

[fields-in-traits](https://internals.rust-lang.org/t/fields-in-traits/6933/13)

and it is quite similar to [niko's fields-in-traits-rfc](https://github.com/nikomatsakis/fields-in-traits-rfc)

## borrows

this helps partial borrowing

[related issue](https://github.com/rust-lang/rfcs/issues/1215)

# Guide-level explanation

# `field`

`field` is is interface that represents field of struct

```rust
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

```rust
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 .......

```rust
struct Bar {
    foo: Foo,
}

```

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

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

```

## `borrows`

`borrows` is a set of `field` to borrow

`borrows` visualises partial borrow

it 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

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

```

### remaining fields with `..`

this will borrow `x` as immutable and others as mutable

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

```

#### negative borrow

this will borrow others except `x`

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

```

### borrowing field of field

this will borrow `foo.x`

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

```

in short

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

```

### examples

```rust
//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

```rust
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

```rust
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`

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

```

you can borrow all fields of `Foo` like this

```rust
...
    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

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

```

borrow only Foo::x

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

```

borrowing fields in typed param

```rust
...
    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

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

```

## `field` and `borrows` in `impl` block

```rust
trait Baz {
...

```

you can declare `field` in trait block

it needs to be implemented when struct implements the trait

```rust
...
    field baz_x: usize;
...

```

borrow all fields of `Self`

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

```

borrow all fields of `Baz`

so it's parital borrow

```rust
...
    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

```rust
...
    borrows f: Self;
...

```

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

```rust
...
    fn field9(&self.{ Self::f }) -> usize;
...

```

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

```

```rust
...
    fn field11(&self.{ Self::f }) -> usize;
}

```

## implementing `trait` with `field` and `borrows`

```rust
impl Baz for Foo {
...

```

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

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

```

implementing `borrows`

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

```

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

```rust
...
    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

```rust
...
    fn field11(&self.{ y }) -> usize {
        self.y
    }
}

```

```rust
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

```rust
trait DerefField {
   type FieldType;
   field deref_field: FieldType;
}

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> {
    type FieldType = T;
    field deref_field = self.value;
}

```

```rust
struct LivingData {
    health: usize,
    hunger: usize
}

trait Living {
    field living_data: LivingData;
    
    pub field health = Self::living_data.health;
    pub field hunger = Self::living_data.hunger;
}

struct Cat {
    living_data: LivingData
}

impl Living for Cat {
    field living_data = Cat::living_data;
}

```

# Reference-level explanation

field should work like re-exporting in module level

there can be a field with different ident pointing same field

field in trait object won't work but you can add a function that returns reference of field

`&T::{ .... }` will work like a type which `&T` or `&mut T` or `&T::{ ..... }` can be implicitally casted into

casting `&T` or `&mut T` into `&T::{ .... }` will borrow every field of it in braces

and won't work if can't borrow it

`&T::{ ... }` will work same as `&T` or `&mut T` in low level like `&mut T` does like `&T`

trait fields will work by storing relative position in the memory

# Drawbacks

Why should we _not_ do this?

# Rationale and alternatives

- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?

# Prior art

[partial borrow](https://github.com/rust-lang/rfcs/issues/1215)

[fields in trait](https://github.com/rust-lang/rfcs/pull/1546)

# Unresolved questions

- What parts of the design do you expect to resolve through the RFC process before this gets merged?
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?

# Future possibilities

something like partial move will be implemented in future then name of `borrows` will need to be changed

we won't need to add `get()` or `get_mut()` for every field the trait is using and now it will only borrow the exact field

---

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [January 23, 2021, 6:15am UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/2 "2021-01-23T06:15:13Z")

</div>

Thanks for this proposal!

The motivation is missing. It currently says what the proposed features can do, but not, why these features are needed.

> [@djdisodo](#):
>
> `field` is an item that represents field in `struct` .

I think the `field` keyword could very well be omitted:

```rust
trait Foo {
    foo: usize;
}

```

The second part of the proposal (`borrows`) seems unnecessarily complex to me. I think a simpler, more familiar syntax would be better, e.g.

```rust
struct Foo(bool, i32);

impl Foo {
    // borrows only the first field of Foo
    fn foo(self @ Self(a, _)) -> bool {
        a
    }
}

```

The `borrows` items seem unnecessary to me. They add a lot of complexity for very little gain.

Note that this proposal currently proposes two distinct features, so it would probably require 2 RFCs.

---

<div class="post-metadata">

**Author:** ![djdisodo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djdisodo/32/7665_2.png) [@djdisodo](https://internals.rust-lang.org/u/djdisodo)\
**Post date:** [January 23, 2021, 1:46pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/3 "2021-01-23T13:46:40Z")

</div>

@Alosothanks, I agree that `field` keyword is unnecessary

```rust
struct Foo(bool, i32);

impl Foo {
    // borrows only the first field of Foo
    fn foo(self @ Self(a, _)) -> bool {
        self.bar(); //<-- 
    }
    fn bar(self @ Self(a, _)) -> bool {
        a
    }
}

```

I saw a similar thing on partial borrow issue, you won't be able to call bar() in foo() in this case

I thougth `field` will help to explain `borrows` that's why I put them together

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [January 23, 2021, 3:13pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/4 "2021-01-23T15:13:08Z")

</div>

> [@Aloso](#):
>
> ```rust
> struct Foo(bool, i32);
> 
> impl Foo {
> // borrows only the first field of Foo
> fn foo(self @ Self(a, _)) -> bool {
> a
> }
> }
> 
> ```

Hmm... does it not look too much like binding a pattern after `@`?  
(e.g. binding both `self` and `a`, [Example](https://gist.github.com/5c30cb33b54f4c4dead492dd135643b6))

Would it perhaps be better instead to spell it like this?

```rust
impl Foo {
    // borrows only the first field of Foo
    fn foo(self : Self(a, _)) -> bool {

```

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [January 23, 2021, 3:33pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/5 "2021-01-23T15:33:46Z")

</div>

This seems to overlap with my proposal, which was postponed because it could possibly be implemented as a crate.

Pre-RFC: [[Idea] Pointer to Field](https://internals.rust-lang.org/t/idea-pointer-to-field/10061/)

RFC: [https://github.com/rust-lang/rfcs/pull/2708](https://github.com/rust-lang/rfcs/pull/2708)

Related Crate: [GitHub - RustyYato/generic-field-projection: This crate was created to implement the ideas in this RFC #rust-lang/rfcs/2708](https://github.com/RustyYato/generic-field-projection/)

---

<div class="post-metadata">

**Author:** ![djdisodo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djdisodo/32/7665_2.png) [@djdisodo](https://internals.rust-lang.org/u/djdisodo)\
**Post date:** [January 23, 2021, 4:54pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/6 "2021-01-23T16:54:45Z")

</div>

![스크린샷(43)](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/6/6f7e9cf0366fee02177cae6f6dd60f67965169da.png)using pointers will restrict chance of optimization and it's not managed by borrow checker

I'm expecting foo.(Foo::x) (for Foo::x and its export) and foo.x to compile in same way and be managed by borrow checker

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [January 23, 2021, 5:06pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/7 "2021-01-23T17:06:54Z")

</div>

The borrow checker has no influence on genrated code _at all_. It is pure compile-time analysis. In fact before we hit LLVM, ~~references and raw pointers are unified into the same representation, so there is no chance of any differences in optimization differences.~~ edit: references and raw pointers are unified to a similar representation (where references get some extra LLVM annotations for optimization purposes), but this isn't a big deal because as @rpjohnst says below, these raw pointers are transient.

I tried all of your examples, and the final generated code has _no difference at all_: [Compiler Explorer](https://godbolt.org/z/a54ds8). There is a small difference in the LLVM IR, but that doesn't matter that much: [Compiler Explorer](https://godbolt.org/z/4Y3hxf).

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [January 23, 2021, 5:47pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/8 "2021-01-23T17:47:08Z")

</div>

> [@RustyYato](#):
>
> The borrow checker has no influence on genrated code _at all_ . It is pure compile-time analysis. In fact before we hit LLVM, references and raw pointers are unified into the same representation, so there is no chance of any differences in optimization differences.

Careful, this is a big oversimplification! _Lifetimes_ and the borrow checker's results are erased, but there is a very big difference between references and raw pointers when it comes to optimization, and this is basically those types' whole reason to exist! For example see [Enable noalias annotations · Issue #54878 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/54878).

It's possible that a field projection library could be implemented in such a way as to avoid this, because it's mostly in the business of offsets and so it could use raw pointers only transiently, but that's a much narrower distinction.

---

<div class="post-metadata">

**Author:** ![djdisodo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djdisodo/32/7665_2.png) [@djdisodo](https://internals.rust-lang.org/u/djdisodo)\
**Post date:** [January 23, 2021, 5:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/9 "2021-01-23T17:49:05Z")

</div>

[https://godbolt.org/z/zq95oz](https://godbolt.org/z/zq95oz) except `use_add` it's usually being optimized and results this (i didn't expected `use_offset` to work)

```rust
example::use_field_test:
        mov eax, 2
        ret

```

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [April 23, 2021, 5:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-field-as-an-item-and-borrows/13886/10 "2021-04-23T17:49:06Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
