Struggling to implement parallel foreach...

Manu turkeyman at gmail.com
Sat Jun 15 02:38:01 UTC 2019


On Fri, Jun 14, 2019 at 3:35 PM Timon Gehr via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On 14.06.19 20:51, Manu wrote:
> > On Fri, Jun 14, 2019 at 8:05 AM Kagamin via Digitalmars-d
> > <digitalmars-d at puremagic.com> wrote:
> >>
> >> On Friday, 14 June 2019 at 09:04:42 UTC, Manu wrote:
> >>> Right, exactly... the compile error should be at the assignment
> >>> of the
> >>> not-shared closure to the shared delegate. The error would be
> >>> something like "can't assign `Context*` to `shared(Context)*`".
> >>> So, the function can certainly exist, but for shared, you
> >>> should get
> >>> an error when you attempt to call it passing the closure to the
> >>> function.
> >>
> >> The shared function attribute means that its context is shared
> >> similar to object methods, the error is an attempt to implicitly
> >> leak unshared data into that shared context, that's why indeed
> >> function itself is incorrect. Declare the variable as shared and
> >> it will work.
> >
> > No, you've misunderstood. The qualifier does NOT apply to the context
> > as it should, that's the issue I'm reporting.
>
> There is a bug, but It appears you don't understand what it is. Why do
> you insist on reporting the bug in a particular wrong way instead of
> trying to understand what is actually going on?
>
> This is not the first time you do this. Sometimes, you spend some time
> on your own to form some partially-correct opinion and then you stick to
> it against all evidence to the contrary.

Ok... Why would a function that receives a context object, which also
explicitly qualifies the context, not apply the qualifier to the
context?

> > Try it with const, it's simpler to understand.
>
> That's because it's a completely different case.

Not even remotely.

  Context*
  const(Context)*
  shared(Context)*

Qualifiers hare a regular and consistent semantic when applied to things.
There are no 'cases' here that I can see... what is the 'case' that I'm missing?

> > You can incorrectly
> > mutate x from a const context.
> >
> > A local function is essentially:
> > void localFun(Context*, Args...);
> >
> > A const local function should be:
> > void localFun(const(Context)*, Args...) const  // <- const applies to
> > the context pointer, as usual.
> > ...
>
> Yes, but this is not "as usual". In particular, this is not how it works
> for `immutable` and `shared`, because it makes no sense.

What do you mean? That's *exactly* how it works with immutable and
shared, and any qualifier applied to any context pointer.
A qualified method accepts a qualified context pointer, and expects
the calling code to supply a valid context argument. There's no magic
here, and there shouldn't be.

> With your
> suggestion it would be impossible to ever call an `immutable` or
> `shared` local function unless all data that is transitively reachable
> from the current stack frame is `immutable` or `shared`, respectively.

Yes, that is **EXACTLY** what my suggestion expects.
The calling code supplies a `Context*`, and all qualifiers other than
`const` would emit the predictable compile error because there is no
implicit conversion from `Context*` to `immutable(Context)*`, etc.
The function itself must still respect the fact that it received a
qualified context, or it's just lying.

> That's clearly useless.

It's not useless at all, because the compiler will still emit the
function, and I can call it by force.
What's _actually_ useless, is having the function accept qualifiers on
the definition that don't do anything. The user shouldn't qualify the
function if they don't want the context to be qualified as they
specify.

> > That does not appear to be the case however.
> > For example:
> >
> > void test()
> > {
> >    int x;
> >    void fun() const
> >    {
> >      pragma(msg, typeof(x)); // should print `const(int)` because
> > typeof(const(Context*).x) == const(int), but it incorrectly prints
> > `int`
> >      ++x; // <- should be an error, but the context pointer is not
> > const, so this compiles!
> >    }
> > }
> >
> > The context pointer is missing the qualifier.
> >
>
> Yes, in this instance, but your actual blocker is that there is no
> `shared` inference for local functions.

It's not 'inference', placing a qualifier after the function parameter
list specifies an absolute and explicit qualification of the context.
const and shared aren't different 'cases', qualifiers apply to the
context, and if that appears to be useless or invalid, or an obvious
compile error because implicit conversion is impossible, then that's
the expected behaviour.
In the case of shared; I can produce the appropriate calling context
and cast it. But I can't write a valid function right now, because the
context qualifier is disregarded.


More information about the Digitalmars-d mailing list