May 25, 2022
On 25.05.22 01:31, Walter Bright wrote:
> On 5/24/2022 3:45 PM, Timon Gehr wrote:
>> On 24.05.22 18:20, Walter Bright wrote:
>>> On 5/24/2022 12:43 AM, Timon Gehr wrote:
>>>> The original example no longer compiles, there are others in that thread. It has not been fixed!
>>>
>>> Other issues should get their own bugzilla issue.
>>
>> You are twisting my words. It's not another issue, it's another _example_. It's just that the pull request only fixed some special case.
>>
>> But sure, not really worth arguing. Whether or not the 15 year old bugzilla issue remains open or is replaced by a new duplicate report does not change much.
> 
> If the fix did not fix other cases, then they are separate bugs. They certainly may be related, but if they require more code, they are separate.
> 

I don't buy that.

> Our whole use of github and bugzilla revolves around a 1:1 correspondence between bug fixes and PRs. A 1:many and many:1 is just not manageable.
> 

The issue is: sometimes there are pull requests that _don't actually fix the issue they purport to fix_. Why should that cause a changelog entry that claims the bug was fixed?
May 24, 2022

On Tuesday, 24 May 2022 at 21:53:36 UTC, Ola Fosheim Grøstad wrote:

>

In short, it says nothing of use. We dont try to attract 50% of all programmers. Even 1% would be huge!

Reread what I wrote in this channel and you'll note that this is very consistent with what I'm saying.

To be successful, you need to be really good at something. You need to be even better than everybody else at this thing. And the 1% of people who really need this thing will be willing to overlook other shortcomings.

In turns, this grows the community, the codebase, the tooling and so on. This grant the resources to make the project good at a second thing and so on.

For instance, I remember about 10 years ago, when Rust was just starting, Andrei mentioned that Rust skipped leg day. This was funny and true: rust has that one thing about ownership it did extremely well, but everything else D was better. Where is rust now and where is D? Why did this happen? Well, the thing is, D is good at many thing, but it's not great at one thing. You therefore don't get that 1% of dev who really want or even need it.

The second thing is capitalizing on these devs. They will build tool and an ecosystem and this is a virtuous cycle. Except we keep breaking this cycles in a few ways:
1/ Ballooning complexity. The most jaring exemple is the attribute soup. The main problem is, most of the code out there is not quite attribute this or that compliant, so interoperability doesn't quite work, and making it work require major efforts, as anyone who contribute to phobos will be able to confirm.
2/ We do not get much benefit from that complexity, in any case, nothing that make it worth the cost. While we have attribute that are supposed to provide some guarantee, they are in practice often unable to provide said guarantee, either because there are hole in the implementation, but more often because there are fundamental design problems with them.
3/ We break these tools constantly, for weak reasons. Making a shorter in/out contract syntax. Making throw an exception. Named arguments. return is now an attribute. etc... All thee change break tools, and do not provide the kind of benefit that can counterract the loss of tooling.

These action taken effectively prevent the ecosystem from growing. Just like bonsai, it get trimmed on a regular basis, so it stays small.

May 24, 2022
On 5/24/2022 4:28 PM, Adam Ruppe wrote:
> We should probably re-open all the other issues that were marked duplicates of this one then, since there's plenty of other examples in there that do still compile without modifications.
> 
> And I'd point out the original example fails to compile for the wrong reason. So it isn't like it is actually fixed at all.

Timon created a clear example that compiles for the wrong reason:

https://issues.dlang.org/show_bug.cgi?id=23136
May 25, 2022
On 25.05.22 01:47, Walter Bright wrote:
> On 5/24/2022 3:55 PM, Timon Gehr wrote:
>> On 24.05.22 19:10, Walter Bright wrote:
>>> On 5/24/2022 12:45 AM, Timon Gehr wrote:
>>>> No. The correct behavior when a delegate literal outlives captured variables is to allocate a closure. This case is not an exception...
>>>
>>> But it isn't a safety problem, as it won't compile.
>>
>> Well, it's still a memory safety problem in @system code, it's just that it's not a soundness issue for @safe.
> ...

Sorry for the confusion, I had accepted your claim without examining your code example in detail as I was in a hurry this morning. You were just mistaken.

> The whole point of @system is to remove the safety checks.
> ...

@system still checks types, it just allows you to do some explicitly unsafe things such as type casts.

> I'm more interested in soundness

There is no soundness. Not in @system code. Not in @safe code.

> than in replicating closure semantics of other languages.
> Especially since the workarounds are simple:
> 
> Replace `int x` with `int* px = new int()`
> ...

Well, I don't think it's exactly this simple as that pointer will be captured by reference.

> I.e. one can always make a closure manually. It's not the end of the world if the compiler doesn't provide a spoonful of sugar for it.
> 
> Don't get me wrong, I'm still interested in adopting good semantics from other languages, it's just that soundness is much more of a priority.
> ...

Ok!

> I do enjoy and appreciate your contributions, too, even if it seems like I'm always arguing with you :-/

Well, it's not my preference either, but I am fine with arguing if it's productive.

I have burned out a couple of times from engaging on the newsgroup though, because nothing got through to you. In this instance the problem seems to be that you are biased towards accepting immediately that stuff is actually not broken without examining closely enough what is going on.

Unfortunately, in such cases, arguing is taking away time and energy from both of us that could be spent trying to tackle those issues in a constructive way.
May 25, 2022
On Tuesday, 24 May 2022 at 23:31:58 UTC, Walter Bright wrote:
> If the fix did not fix other cases, then they are separate bugs. They certainly may be related, but if they require more code, they are separate.
>
> Our whole use of github and bugzilla revolves around a 1:1 correspondence between bug fixes and PRs. A 1:many and many:1 is just not manageable.

But they are not, and this is why this doesn't get resolve. These aren't bugs, there is a design issue.

You have essentially two way to go at it:
1/ Allocate a closure int he loop. This remains unsound by itself because the qualifier of the closure is not tracked, which lead to possible implicit sharing for instance and other nastyness. There is not enough information in the typesystem to solve this, so going at it bug by bug will simply be an exercise in wack a mole.
2/ Prevent capture of object beyond their lifetime. This require ownership and lifetime tracking. DIP1000 doesn't have the depth required to do so adequately - it lacks the recursiveness required to track indirections - so once again, fixing bugs one by one is an exercice in wack-a-mole.

Because the design is inadequate to begin with, you can only fix presumably more common holes (because they got reported first) by creating more uncommon ones at best, make no progress at worse.

To fix these problems, you actually need to think of the system it term of the invariant that each part either require or imply, and find where these do not match.

these problem with closure are quite complex, but there is an exemple of this that is much simpler and easy to grok: final switch vs non promoting binary operation on enums.

One assumes the invariant that enum are bounded to the set of values declared in the enum, but the second doesn't effectively relegating the enums to be a subtype of their base class. They just cannot be both within a sound system.

There is no amount of getting test cases to pass that will fix this problem with enums, because it is a design problems. Almost all soundness problems are, BTW.
May 25, 2022
On 25.05.22 01:40, Walter Bright wrote:
> On 5/24/2022 4:21 PM, Timon Gehr wrote:
>> For containers: Just consider a struct wrapping a built-in slice.
>>
>> struct Slice(T){
>>      T[] slice;
>> }
>>
>> T[] is a subtype of const(T)[], but Slice!T is not a subtype of Slice!(const(T)). In general this cannot be guaranteed, but containers may need to be able to allow this kind of conversions.
> 
> What about:
> 
>      struct Slice(T) { T[] slice; int* p; }
> 
> ? A const applied to T will not affect int*, but if the const automatically was transferred to Slice, it would, and that would be wrong. It seems you're asking for a special case, and as we all lament, special cases lead to corner cases with special problems.
> ...

Not really. What's needed is some feature that _allows_ implementing a correct slice wrapper. I am not asking for the slice wrapper above to do the right thing by default.

> 
>> For ranges:
>>
>> E.g., here, x is a const slice and can be mapped. The resulting const value cannot be used as a range anymore.
>>
>>
>> ```d
>> import std.algorithm;
>> void main(){
>>      const x=[1,2,3,4];
>>      const y=x.map!(v=>2*v); // ok
>>      const z=y.map!(v=>2*v); // error
>> }
>> ```
>>
>> This kind of thing should just work, but there is no way to strip away the topmost const for a MapResult.
> 
> const(int**) p;
> cast()(p) produces a const(int*)*
> 
> I.e. cast() strips the "head" qualifiers.
> ...

It often strips more than that.

struct S(T){ T* p; }

const(S!int) s;
auto t=cast()s; // this is just an S!int, but stripping the "head" qualifiers would give us something like an S!(const(int)).

I am not suggesting `cast()` should behave like this by default, because as you point out, it is not what you want in general. But there is a problem.
May 24, 2022
On 5/24/2022 4:36 PM, deadalnix wrote:
> When I report bug, they get fixed and it's great.
> 
> When I report design problem, they get treated as bugs and we never get to the root of the issue and I'm wasting my time.


I'm sorry, there is nothing I can do with this as there's no link.

We *do* have a process for this:

1. bugs get reported on bugzilla
2. design bugs get reported on bugzilla as Enhancement Requests
3. significant design proposals get submitted as DIPs

What does not work and is not part of the process:

Reporting 1, 2 or 3 on the n.g. because then they scroll off the screen and vanish, as there is no organized way to deal with them.

For discussion of ideas, if you want them to go anywhere, submit them to 1, 2 or 3. Then start a n.g. discussion, with a link to 1, 2 or 3.

People complain that the D Foundation does not have a process. It does. But it doesn't work if people ignore the process and just post things to the n.g. The forums are not a bug database.

It also doesn't work when people (not you) post bug reports to *closed* PR's! Nobody looks at closed PRs. That can't possibly work.

BTW, The C and C++ Standards committees will TOTALLY IGNORE any and all proposals that are not formal proposals submitted to the committee.

May 25, 2022
On 25.05.22 01:47, Walter Bright wrote:
> 
> I do enjoy and appreciate your contributions, too, even if it seems like I'm always arguing with you :-/

I guess this is as good an opportunity as any to also say that I highly appreciate the huge amount of work that you have invested into D. There's a lot that already works great.
May 24, 2022
On 5/24/2022 4:47 PM, Timon Gehr wrote:
> The issue is: sometimes there are pull requests that _don't actually fix the issue they purport to fix_. Why should that cause a changelog entry that claims the bug was fixed?

If the supplied example works correctly, the bug is closed.

Is it really too much to ask for:

1. people to submit bug reports to bugzilla, not the n.g.?

2. provide an example of the bug?

Making me debug the provided example and/or guess what the submitter actually intended is too much to ask. (Often the subject line is completely wrong, too, and I often fix them.)

I've been cutting and pasting your n.g. bug reports to bugzilla. This really does not scale.
May 25, 2022
On 25.05.22 02:08, deadalnix wrote:
> 
> 1/ Allocate a closure int he loop. This remains unsound by itself because the qualifier of the closure is not tracked, which lead to possible implicit sharing for instance and other nastyness. There is not enough information in the typesystem to solve this, so going at it bug by bug will simply be an exercise in wack a mole.

Well, I would not call this specific case "whack-a-mole". Doing this is actually just a net positive as any unsoundness that remains is orthogonal to it and does not require a loop to trigger.

Anyway, the nice thing about closure context type checking in particular is that it's actually not so hard to get right, but it is certainly true that someone has to do a comprehensive implementation.