Alternative to Rust's borrow checking and explicit lifetimes?

Timon Gehr timon.gehr at gmx.ch
Thu Apr 16 02:39:27 UTC 2020


On 14.04.20 12:18, Walter Bright wrote:
> On 4/13/2020 11:18 PM, lstfmk wrote:
>> While learning Rust, I came up with an alternative strategy to prove 
>> memory safety. So I created this thread on the Rust user forums:
>> https://users.rust-lang.org/t/alternative-to-borrow-checking-and-explicit-lifetimes/40906 
>>
>>
>> The post is a rough sketch of my strategy and is certainly could be 
>> more thorough. It is intentionally so such that you get a gist of the 
>> strategy. Though I am certain D could not implement this without 
>> breaking backward compatibility by a huge margin, I post here just so 
>> that it could be at least considered as I've heard that work on a 
>> lifetime/borrowing system is going on to be included in D.
>>
>> My strategy doesn't impose any borrow restrictions and doesn't require 
>> explicit lifetime annotations at all, while seeming to provide the 
>> same guarantees that Rust's borrow checker currently provides. 
>> Currently, the borrow checker imposes the limit that you can have 
>> either one mutable reference to an object (or) multiple immutable 
>> references to the object. This exclusiveness currently makes Rust feel 
>> very restrictive, not to mention explicit lifetime annotations.
>>
>> Regarding analysis complexity, I suspect my strategy is much simpler 
>> than Rust's current borrow checker since it works with scope-based 
>> lifetimes very well. Rust's technique is to lower the Rust code to a 
>> middle-level IR to take into account what is called non-lexical 
>> lifetimes(NLL) which are inferred using some sort of liveness 
>> analysis. This NLL consideration was added 2 years ago before which 
>> Rust was even more restrictive.
> 
> Thank you for posting this, it's good to see more effort in this direction.
> 
> D's current Ownership/Borrowing system

I would not call it that. It does not currently enforce ownership or 
borrowing invariants.

> does do NLL, and uses Data Flow Analysis to achieve it.
> ...

Do you have an example where that helps? Testing with DMD 2.091.0, it 
does not seem possible to encode the simple examples on 
https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.html

void ignore(int* p){}
void main()@live{
     int x=5;
     auto p=&x;
     x=3; // should fail, but compiles
     *p=4;
     ignore(p); // not necessary in Rust
}

void ignore(int* p){}
void main()@live{
     int x=5;
     auto p=&x;
     *p=4;
     x=3;
     ignore(p); // not necessary in Rust
}

Maybe the problem is that taking a local variable's address results in 
an owning pointer instead of a borrowing pointer, but that would not 
make any sense. How can a pointer ever own stack memory? Also, it 
appears that in a @safe function, it is impossible to ever dispose of 
such a pointer as it is both `scope` and has to be freed explicitly.

@live also allows the address of the same local variable to be taken 
multiple times:

void main()@live{
     int x=5;
     auto p=&x;
     auto q=&x;
     *p=4;
     *q=5;
     writeln(*p," ",*q);
     ignore(p);
     ignore(q);
}

> Like Rust, D's O/B checking is done on a per-function as a whole basis, 
> and relies on the function signatures being correct.
> ...

Rust _checks_ that the function signatures are correct and lifetime 
annotations allow the analysis to remain precise when it crosses 
function boundaries.


More information about the Digitalmars-d mailing list