On Borrow Checking
jmh530
john.michael.hall at gmail.com
Wed May 7 14:47:49 UTC 2025
On Tuesday, 6 May 2025 at 20:12:18 UTC, Dukc wrote:
> On Tuesday, 6 May 2025 at 14:48:27 UTC, jmh530 wrote:
>>
>> It might be helpful to example where Rust's version of some
>> code let's you prove something is safe with the borrow
>> checker, but D's version doesn't.
>
> You're right. Have a look at my post earlier on this thread:
>> On Tuesday, 29 April 2025 at 17:12:41 UTC, Walter Bright wrote:
>>> So I implemented a borrow checker for D, and it is enabled by
>>> adding the `@live` annotation for a function, which turns on
>>> the borrow checker for that function. There are no syntax or
>>> semantic changes to the language, other than laying on a
>>> borrow checker.
>>
>> There's a difference.
>>
>> In Rust, as I understand it, if you have a function like
>>
>> ```Rust
>> fn free(ptr: MyCustomPointer)
>> { // ...
>> }
>> ```
>>
>> it is 100% safe to use. The compiler will not let you
>> double-free or use after free, unless you use the `unsafe`
>> block to do so.
>>
>> But you can't have
>>
>> ```D
>> @trusted void free(MyCustomPointer ptr)
>> { // ...
>> }
>> ```
>>
>> in D because it would be unsafe to use from a non-`@live`
>> function.
>>
>> If we had a way to say that "this function can be called from
>> `@safe`, if and only if it's usage is guarded with `@live`"
>> then it would be equal to the Rust borrow checker.
Ah, I remember that. Thanks.
Just to be clear, the @trusted function you provide could be
called by an @safe function, but your point is that it may
actually be unsafe to do so. The real goal is to enable more code
to actually be safe, not to just slap @trusted on things.
The examples in the @live spec don't reference @safe. But it does
have an example of a non- at live release function that is called by
an @live test function that prevents use after free.
I can think of a few different ways forward (by no means limited
to just this)
1) Do @safe inference on @live functions. I assume a body is
needed on @live functions (Rust requires a body unless a trait or
extern function, and extern is only allowed in unsafe code). So
that might be good idea on its own merits.
That being said, it doesn't really help you if the @live function
is calling an @system function. Also, @live functions can call
non- at live functions (although for an @safe @live function all the
functions called by it need to be @safe/@trusted too), so it
wouldn't necessarily be a transitive inference all the way down
(i.e. it hits the first unattributed function and becomes
@system).
2) Enhance the @safe definition so that an @safe @live function
can call an @system function so long as the function it calls
abides by certain restrictions. Obviously, the spec would need to
clearly state what the restrictions are. One limitation would be
that to verify that a @system function abides by these
restrictions would require having the function body.
3) Add a @safeiflive attribute such that the function is @safe if
called by a @live function and @system otherwise. As above, the
team would need to pin down exactly what is allowed. After all,
why couldn't it just be marked @safe? What @safe restrictions
could be relaxed if @live is being enforced. Would require some
thought, I imagine, but probably useful to think about. The
downside is that it's more attributes.
4) Add @trustediflive, similar to above such that it is @trusted
if called by a @live function and @system otherwise. Let's the
user make the decision, more flexible. I think @trustediflive is
kind of in line with what you were suggesting.
More information about the Digitalmars-d
mailing list