| |
| Posted by Nick Treleaven in reply to Walter Bright | PermalinkReply |
|
Nick Treleaven
Posted in reply to Walter Bright
| On Monday, 18 March 2024 at 22:46:27 UTC, Walter Bright wrote:
> Some easy cases can be handled easily(!). But to do it reliably, DFA is required. And DFA makes the front end slow.
>
> If one doesn't do DFA, then I will be subjected to endless bug reports where people find a case that needs DFA to resolve.
Sorry my reply wasn't rigorous enough.
>> if (i) a = new A();
>
> If `a` is non-nullable, this line could be made to error because there is no `else` branch that also initializes `a`. This is what cppfront does.
I think this is workable without DFA, the compiler just tracks when a variable is initialized. There is never a state where a variable may be both initialized and not initialized (e.g. no dependency on whether a jump instruction was taken at runtime). Do you think this is reasonably cheap time cost?
>> if (i) a.bar();
>
> If `a` is nullable, this line is an error because you are calling a method that needs an A when (from the DFA-less compiler's point of view) you might only have a null pointer.
>
> To handle that, you either:
> * `assert(a)` before `a.bar()`, and the compiler assumes `a` is not null and in release mode there is only a hardware null check.
This alone indeed does not work in general as `a` may become null after the assert and before it is dereferenced.
> * Call a function to force-unwrap the nullable type to a non-null type, e.g. `a.unwrap.bar()`. This function can be a no-op in terms of hardware, but requiring calling it makes the programmer aware that a possible null dereference (at least from the compiler POV) may occur.
This works and requires no analysis. The function internally just casts to non-null, the advantage being that the call is explicit to the programmer, alerting them and reviewers to possible program abort.
This alone might be workable in theory but in practice it would probably be annoying in some cases where the compiler could help.
> * Rewrite the if statement to `if (a)`. That is actually better code because you would need to check that `i` hadn't changed in between the two if statements, which might be long, to understand the code.
Like assert, this is not workable in the general case. However, declaring a new variable could work:
```d
if (auto b = a) {
b.bar;
}
```
There are 2 options:
1. The type of `b` is non-nullable. This is a breaking change. There would need to be some syntax for opting in to make `b` nullable.
2. We have some other syntax for `b` being non-nullable.
Workable?
|