On Borrow Checking

Walter Bright newshound2 at digitalmars.com
Sat May 10 15:34:28 UTC 2025


On 5/10/2025 5:25 AM, Manu wrote:
>>     1. Function declarations don't have a body, so there's no way to inspect the
>>     body.
> A prototype without a body must always trust the declaration. You must simply 
> assume that presence of `scope` on an arg asserts that the parameter won't be 
> retained by the call, and the caller can also bank on that fact; ie, using 
> temp/stack memory to allocate an argument.

Yes, of course, that's how dip1000 works.

>>     2. Inspecting all the bodies means compilation gets slowed down quite a bit.
> If you don't want escape analysis, don't write `scope`; point is, why do you 
> need to write TWO attributes together for the first one (which is itself 
> strictly optional) to take effect?

`scope` is needed to say that a pointer being passed does not escape. `return` 
is needed to specify that an escape via the function's return is allowed.


>>     3. Chicken-and-egg problems when inferring attributes when there are loops in
>>     the function call flow graph.
> I don't follow.

f calls g calls h calls f

You can't infer attributes of f because it depends on f. You can't infer 
attributes of g because it depends on f which depends  on g. And so on. To deal 
with this problem requires constructing Data Flow Equations and then solving 
those equations by iterating and converging on a unique solution. This is what 
the code in the link to gflow.d does. It's in the comments.

Unfortunately, building and solving the DFE's is slow. This is why the optimized 
builds are much slower than non-optimized builds. This is why the simplistic DFA 
is used to infer attributes rather than DFA, because we want fast non-optimizing 
builds.


> Is it something like; a template which receives an arg but doesn't explicitly 
> state `scope` just spend time to try and infer `scope` because a caller of that 
> template may rely on that attribute inference?

Of course.

> 
>      > I do want to add `scope` to pointers and ref arguments, but I don't see any
>      > reason that I should have to attribute `live`... why isn't `scope` enough to
>      > enable escape analysis?
> 
>     The DFA (Data Flow Analysis) required to determine whether a pointer is the
>     "owner" or not at each point in the function is considerably more complex than
>     just checking for scope-ness. DFA equations are generated and then solved
>     iteratively.
> 
>     The code required to do it is:
> 
>     https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ob.d
>     <https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ob.d>
> 
>     which is very similar to the DFA performed by the optimizer:
> 
>     https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/gflow.d
>     <https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/gflow.d>
> 
> 
> Yeah but I still don't get it; if you don't want escape analysis, don't write 
> `scope`.

Yes, and then you cannot call that function with a scope pointer.


> If you do write it, you have clearly and unambiguously indicated that 
> you DO want escape analysis, so it should happen.
> I can't see any reason a second unrelated attribute should be required in 
> conjunction to make the first one work... you write `scope` thinking it will be 
> effective, and then by not writing (or forgetting to write) the other thing, 
> your code is now lying to you. You won't know this until you are bitten by the 
> escape bug that you were trying to prevent; making the sutuation actually 
> *worse* than useless, because when you're trying to track down your bug, you 
> will see the attribute, and continue looking elsewhere.
> `scope` should work when you write it; period. If that is to say that writing 
> `scope` infers the other attribute, whatever... but it's not a reasonable 
> situation where `scope` silently does nothing and confuses or misleads the author.

It does work when you write it. The "second unrelated attribute" (which I assume 
is the "return" attribute) is necessary to indicate if the scope'd pointer 
returns or not. Not having the `return` attribute means the following code is 
impossible to write:

```
int* = foo(scope int* a) { return a; } // error: `a` is escaping via return!
scope int* p = ...;
scope int* q = foo(p);
```


More information about the Digitalmars-d mailing list