March 01, 2018
On Wednesday, 28 February 2018 at 23:58:44 UTC, Jonathan M Davis wrote:
> On Wednesday, February 28, 2018 19:43:07 Kagamin via Digitalmars-d wrote:
>> On Wednesday, 28 February 2018 at 14:05:19 UTC, Jonathan M Davis
>>
>> wrote:
>> > [...]
>>
>> Doesn't difficulty depend on what exactly to get right? It's not a spherical problem in vacuum.
>
> Feel free to discuss any code-flow analysis issues with Walter, but he's consistently been against using it for much of anything whenever I've seen him discuss it. Not even stuff like VRP covers multiple lines of code, because doing so would require code-flow analysis. And he's specifically said that he's against using it for detecting when a null pointer is dereferenced. IIRC, he's stated that dmd's optimizer uses code-flow analysis for some stuff, but for anything that involves putting it in the frontend where the behavior would have to be encoded in the spec, he's been against it.
>
> - Jonathan M Davis

Isn't DIP1000 [1] basically code flow analysis and implemented (kinda?) in dmd with -dip1000 now?

[1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md
March 01, 2018
On Wednesday, 28 February 2018 at 15:25:40 UTC, SimonN wrote:
> My gripe is that the necessarily-nullable class reference doesn't express the intent.
> Either a codebase must rely on silent conventions or every function with asserts.

I've put up a little experiment that you may be interested in for this part of the problem at least, also a little bit of compile time help because D treats dot on pointers and non pointers the same, it makes for some nice syntax:

class C {
    int i = 3;
}

auto a = no!C;

if (auto c = a.unwrap) {
    writeln("not here: ", c.i);
}
a.dispatch.i; // not ideal, but is at least safe no op.

a = some(new C());

if (auto c = a.unwrap) {
    writeln("here: ", c.i);
}

If you're interested: https://github.com/aliak00/optional

Syntax allowing:
Optional!C = null;

is not there yet, but I think is doable because typeof(null) is distinguishable. So with an optional type this can be well defined as "none" internally as well

Not ideal I know, but maybe a start to see where it can go?

> It's merely sad to see D, with all its powerful static inspection, rely on runtime tests for nulls while other languages (Kotlin, Zig, and 2017 C#) rule null out at compile-time, as if it's the most natural thing in the world.

Yeah, I whole heartedly agree with this. Maybe is an exposure thing? I remember seeing a talk (by I think the kickstarter people) that said after migrating to swift (from objective-c) their crash reports because dropped significantly (my brain for some reason remembers this to be zero, but I'm not sure and I can't figure out which talk this was).

Cheers,
- Ali

March 01, 2018
On Thursday, March 01, 2018 14:59:38 aliak via Digitalmars-d wrote:
> On Wednesday, 28 February 2018 at 23:58:44 UTC, Jonathan M Davis
>
> wrote:
> > On Wednesday, February 28, 2018 19:43:07 Kagamin via
> >
> > Digitalmars-d wrote:
> >> On Wednesday, 28 February 2018 at 14:05:19 UTC, Jonathan M Davis
> >>
> >> wrote:
> >> > [...]
> >>
> >> Doesn't difficulty depend on what exactly to get right? It's not a spherical problem in vacuum.
> >
> > Feel free to discuss any code-flow analysis issues with Walter, but he's consistently been against using it for much of anything whenever I've seen him discuss it. Not even stuff like VRP covers multiple lines of code, because doing so would require code-flow analysis. And he's specifically said that he's against using it for detecting when a null pointer is dereferenced. IIRC, he's stated that dmd's optimizer uses code-flow analysis for some stuff, but for anything that involves putting it in the frontend where the behavior would have to be encoded in the spec, he's been against it.
> >
> > - Jonathan M Davis
>
> Isn't DIP1000 [1] basically code flow analysis and implemented
> (kinda?) in dmd with -dip1000 now?
>
> [1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md

DIP 1000 operates based on the type. As I understand it, it looks at the fact that something is scope or not and then determines whether a particular operation is valid or not based on whether the operation could result in a reference to the data escaping. An operation is then valid or not regardless of what other lines in the code are doing. As such, if I understand correctly, code-flow analysis isn't really necessary, just like code-flow analysis isn't necessary to determine what's valid or not when const is involved.

- Jonathan M Davis

March 01, 2018
On Thursday, 1 March 2018 at 19:10:29 UTC, Jonathan M Davis wrote:
> DIP 1000 operates based on the type. As I understand it, it looks at the fact that something is scope or not and then determines whether a particular operation is valid or not based on whether the operation could result in a reference to the data escaping. An operation is then valid or not regardless of what other lines in the code are doing. As such, if I understand correctly, code-flow analysis isn't really necessary, just like code-flow analysis isn't necessary to determine what's valid or not when const is involved.
>
> - Jonathan M Davis

Ah right, makes sense yep. Thanky!
March 02, 2018
On Wednesday, 28 February 2018 at 23:58:44 UTC, Jonathan M Davis wrote:
> he's stated that dmd's optimizer uses code-flow analysis for some stuff, but for anything that involves putting it in the frontend where the behavior would have to be encoded in the spec, he's been against it.

The compiler can actually detect simple cases of null dereferences if optimizations are turned on, "-O", due to the optimizer using flow analysis.

--
/Jacob Carlborg
March 02, 2018
On Wednesday, 28 February 2018 at 14:05:19 UTC, Jonathan M Davis wrote:
> I expect that pretty much anything you propose that requires code flow analysis is DOA. Walter is almost always against features that require it, because it's so hard to get right, and the places that D does use it tend to have problems (e.g. it's actually quite trivial to use a const or immutable member variable before it's initialized).

Honestly, this is not that hard. It's very hard in DMD because it doesn't go through an SSA like form at any point. It's rather disappointing to see the language spec being decided upon based on design decision made in a compiler many years ago.
March 02, 2018
On Friday, 2 March 2018 at 09:59:53 UTC, deadalnix wrote:
>
> Honestly, this is not that hard. It's very hard in DMD because it doesn't go through an SSA like form at any point. It's rather disappointing to see the language spec being decided upon based on design decision made in a compiler many years ago.

And how easy is transformation into SSA ?
that's not all loads and stores ?
March 02, 2018
On Friday, 2 March 2018 at 10:41:05 UTC, Stefan Koch wrote:
> On Friday, 2 March 2018 at 09:59:53 UTC, deadalnix wrote:
>>
>> Honestly, this is not that hard. It's very hard in DMD because it doesn't go through an SSA like form at any point. It's rather disappointing to see the language spec being decided upon based on design decision made in a compiler many years ago.
>
> And how easy is transformation into SSA ?
> that's not all loads and stores ?

It's the single assignment the key...

March 02, 2018
On Thursday, 1 March 2018 at 16:37:02 UTC, aliak wrote:
> I've put up a little experiment
> If you're interested: https://github.com/aliak00/optional

Nice! Optional is like std's Nullable with extra bells and whistles to make it as painless as you can offer it. I've read all of Optional's source, skimming the dispatching introspection magic, and it's a concise wrapper that is as transparent as it can get.

I can envision using this Optional type whenever I want nullable class reference, and use normal D class references as non-nullable references together with a codebase-wide rule that assigning null to normal D references is always a bug.

Even the generated compiler error messages are good: Optional!C x = some(new C()); int y = x; // Error: Cannot implicitly convert from Optional!C to C.

> a.dispatch.i; // not ideal, but is at least safe no op.

Hah, I've toyed with some examples, and this stuck out as verbose because everything else was really smooth. Optional!int dispatches wonderfully without extra syntax, whereas class C {}; Optional!C needs the extra dispatch before calling methods.

-- Simon
March 03, 2018
On Friday, 2 March 2018 at 19:47:23 UTC, SimonN wrote:
> I can envision using this Optional type whenever I want nullable class reference, and use normal D class references as non-nullable references together with a codebase-wide rule that assigning null to normal D references is always a bug.

Ay, maybe you can even have a type that enforces non nullable references?

(not tested):
struct NonNull(T) if (isPointer!T || is(T == class))
{
  T value;
  alias value this;
  this(Args...)(Args args) { this.value = new T(args); } // always force creation
}


> Hah, I've toyed with some examples, and this stuck out as verbose because everything else was really smooth. Optional!int dispatches wonderfully without extra syntax, whereas class C {}; Optional!C needs the extra dispatch before calling methods.

Yeah, it's unfortunate. If D had custom operators then it could've been  a?.f or whatever :(

So I had to either have a custom function that starts a dispatch chain or implement opDispatch directly inside Optional. The problem with the latter is that means if type T has any of the functions that are part of Optional's interface, they are basically un-callable unless unwrapped first. I found this unacceptable.

I'm going to experiment with moving Optional's methods out as free functions when I get the chance. Then the dynamics between UFCS/dispatch become a bit weird. And I'm not sure how to work range functionality in as free functions, but let's see.

If you know of other ways though I'm all ears :)

Cheers