On Monday, 11 March 2024 at 19:22:54 UTC, Richard (Rikki) Andrew Cattermole wrote:
>On 12/03/2024 4:31 AM, bachmeier wrote:
>On Monday, 11 March 2024 at 08:48:47 UTC, Richard (Rikki) Andrew Cattermole wrote:
>On 11/03/2024 9:16 PM, Alex wrote:
>So I don't see any errors or warnings from compiler when I use uninitialized variable |a| and don't see any exception with backtrace in runtime (application is build in debug mode).
Is it expected behavior? Looks like it is not very safe approach and can lead to very unpleasant memory errors...
This is expected behavior.
The variable a was default initialized to null.
D has not got type state analysis as part of it, so it cannot detect this situation and cause an error.
It is at the top of my todo list for memory safety research for D, as the IR it requires enables other analysis and provides a framework for it to exist in.
Rather than doing that, couldn't the compiler say A a;
is not valid inside @safe
?
One of the improvements for type state analysis I want to make is for methods:
class Foo {
void func(this'nonnull);
}
Instead of:
class Foo {
void func(this'reachable);
}
That'll catch it when you try to call something.
However I'm not sure if disallowing null entering is a great idea, its going to enter through other methods so you might as well embrace catching that as well.
What I've never understood is the valid use case for A a;
that would justify that line compiling. I don't do much with classes, but the same thing comes about with structs. Why would it make sense to write code like this, particularly if you've marked it @safe?
struct Foo {
double n;
string s = string.init;
}
Foo * f;
// Crashes
writeln(f.n);
Foo * f = void;
// Doesn't crash but gives wrong output
writeln(f.n);
Foo * g;
// Crashes
g.n = 3.3;
Foo * g = void;
g.n = 3.3;
// Correct output
writeln(g.n);
// Crashes
writeln(g.s);