Escaping objects and what is escape analysis modelling anyway?

Dukc ajieskola at gmail.com
Mon Jul 27 16:27:31 UTC 2026


On Saturday, 25 July 2026 at 14:52:30 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
> An example of this is you can utilize conditionals to model 
> relationships:
>
> ```d
> int* returnCond(bool cond, int* obj)
> {
>     if (cond)
>         return null;
>     else
>         return obj;
> }
> ```
>
> So this could have a graph that looks like:
>
> ```
> [
>     ( if (params[0] == true)
>         return = null
>     ),
>     ( if (params[0] == false)
>         return = params[1]
>     )
> ]
> ```

Probably the compiler can't rely on this, other than for 
optimisations, unless we'll also have attributes to specify this 
manually. Otherwise `returnCond` couldn't be put to a `.di` file, 
nor could you type a function pointer so that you could call it 
like this.

> Do the following functions have the same relationship between 
> their function parameter and return value?
>
> ```d
> int** rel1(int** param) => param;
> int** rel2(ref int* param) => ¶m;
> ```
>
> Yes and no.
> A big part of the problem here is `rel2`, you can look at it 
> and think oh I know it's got two cells, just like `rel1`!
> And that is true as far as what you should have access to.
> But its not; it's actually the same parameter as the first 
> `rel1`, but you've specified that the first indirection is 
> guaranteed to be non-null and should be ignored.
> This gives you three cells, with the first being hidden to the 
> user, and the second being automatically dereferenced.
> That is storage of the parameter, pointer to `int*` that was 
> passed in, and then the `int*` itself.
>
> Knowing this allows us to model function calls of functions 
> like these and know that the assert will hold true during 
> compilation

I'm afraid you have misanalysed this and might be basing your 
escape analyser on sand.

If this was C++ you would be right, since calling a C++ function 
with a `&` reference to null is undefined behaviour. However, the 
D spec doesn't say so (nor could it, since it's allowed in 
`@safe`. Could in principle be implementation-defined, though), 
and in fact a `ref` variable residing at null will [not even 
crash](https://forum.dlang.org/post/flutpcacmrxoqmnshrrw@forum.dlang.org) if you don't use it anyhow. It seems likely this is the intended behaviour, though I don't have a confirmation.


> The `rel1` and `rel2` have two separate attributes `return` and 
> `return ref`.
> And `rel3` has another `return scope ref` on top of that.
>
> When really the differentiation is just: "am I returning the 
> outermost object?"
>
> This is not the only issue with DIP1000, but it's a pretty big 
> one.
> That has led to the D community not understanding how or why 
> DIP1000 works the way that it does.
> It's not how the attributes are presented; it's what the 
> attributes are representing.

This is certainly one way to view it. However, the differentation 
DIP1000 is making isn't any more complex: either you're 
(potentially) returning the `ref` address, or the address inside 
the variable. Two distinct cases, no more, just like in your 
formulation.

So I still think the DIP1000 confusion about the return attribute 
is mostly in it's representation (when does `return` mean `return 
ref`, when `return scope`), not in the very idea. Yours would be 
about as hard to understand.


More information about the Digitalmars-d mailing list