September 13, 2014
On Saturday, 13 September 2014 at 16:51:09 UTC, Timon Gehr wrote:
> s.bar((int* p){ ++*p; });

Huh? inout is for functions, which don't modify their arguments.
September 13, 2014
On 09/13/2014 07:48 PM, Kagamin wrote:
> On Saturday, 13 September 2014 at 16:51:09 UTC, Timon Gehr wrote:
>> s.bar((int* p){ ++*p; });
>
> Huh? inout is for functions, which don't modify their arguments.

With Jakob's code working, this would not be warranted. (But the situation needs to change in any case. The inout delegate semantics DMD 2.066.0 implements cause type unsoundness as explained here: https://issues.dlang.org/show_bug.cgi?id=10850 .)

If inout should still guarantee non-modification in the future, then nested inout functions will need to introduce their own inout context (i.e. the inout qualifier of the nested function should be incompatible with the inout qualifier of the enclosing function.) I assume this is a major PITA to implement in DMD, and it also leads to growing pains that are hard to counter without enhancing the syntax, hence the current semantics.

In any case, why is it important that inout functions are guaranteed not to change their arguments, even if they are mutable and the mutation is from within a delegate that was passed to such functions for this purpose?
September 13, 2014
On Saturday, 13 September 2014 at 18:36:53 UTC, Timon Gehr wrote:
> On 09/13/2014 07:48 PM, Kagamin wrote:
>> On Saturday, 13 September 2014 at 16:51:09 UTC, Timon Gehr wrote:
>>> s.bar((int* p){ ++*p; });
>>
>> Huh? inout is for functions, which don't modify their arguments.
>
> With Jakob's code working, this would not be warranted.

Huh? See rationale in https://issues.dlang.org/show_bug.cgi?id=1961

> If inout should still guarantee non-modification in the future, then nested inout functions will need to introduce their own inout context (i.e. the inout qualifier of the nested function should be incompatible with the inout qualifier of the enclosing function.) I assume this is a major PITA to implement in DMD, and it also leads to growing pains that are hard to counter without enhancing the syntax, hence the current semantics.

I think, it can be more or less simple without syntax enhancements, see the description of how it can be implemented.

> In any case, why is it important that inout functions are guaranteed not to change their arguments, even if they are mutable and the mutation is from within a delegate that was passed to such functions for this purpose?

The same way const is important: it makes code easier to reason about.
September 13, 2014
On Saturday, 13 September 2014 at 18:36:53 UTC, Timon Gehr wrote:
> (But the situation needs to change in any case. The inout delegate semantics DMD 2.066.0 implements cause type unsoundness as explained here: https://issues.dlang.org/show_bug.cgi?id=10850 .)

BTW, how the change manifests? Your examples show the qualifier is not really bound to the outermost function.
September 13, 2014
On Saturday, 13 September 2014 at 20:01:49 UTC, Kagamin wrote:
> On Saturday, 13 September 2014 at 18:36:53 UTC, Timon Gehr wrote:
>> (But the situation needs to change in any case. The inout delegate semantics DMD 2.066.0 implements cause type unsoundness as explained here: https://issues.dlang.org/show_bug.cgi?id=10850 .)
>
> BTW, how the change manifests? Your examples show the qualifier is not really bound to the outermost function.

Ah, I see, but the error message is strange.
September 13, 2014
On 09/13/2014 09:58 PM, Kagamin wrote:
> On Saturday, 13 September 2014 at 18:36:53 UTC, Timon Gehr wrote:
>> On 09/13/2014 07:48 PM, Kagamin wrote:
>>> On Saturday, 13 September 2014 at 16:51:09 UTC, Timon Gehr wrote:
>>>> s.bar((int* p){ ++*p; });
>>>
>>> Huh? inout is for functions, which don't modify their arguments.
>>
>> With Jakob's code working, this would not be warranted.
>
> Huh? See rationale in https://issues.dlang.org/show_bug.cgi?id=1961
> ...

All the examples there keep their non-modification guarantees.
Modifications to inout parameters are visible at the call site.

>> If inout should still guarantee non-modification in the future, then
>> nested inout functions will need to introduce their own inout context
>> (i.e. the inout qualifier of the nested function should be
>> incompatible with the inout qualifier of the enclosing function.) I
>> assume this is a major PITA to implement in DMD, and it also leads to
>> growing pains that are hard to counter without enhancing the syntax,
>> hence the current semantics.
>
> I think, it can be more or less simple without syntax enhancements, see
> the description of how it can be implemented.
>

Even without going into details, it is easy to appreciate the fact that erasing type information while enforcing type safety invariably tends to lead to pain some way down the road. E.g. the inout qualifier of the enclosing function should still be fully compatible with _itself_ even when data is accessed and modified from the nested function.
September 14, 2014
On Saturday, 13 September 2014 at 19:58:16 UTC, Kagamin wrote:
> On Saturday, 13 September 2014 at 18:36:53 UTC, Timon Gehr wrote:
>> On 09/13/2014 07:48 PM, Kagamin wrote:
>>> On Saturday, 13 September 2014 at 16:51:09 UTC, Timon Gehr wrote:
>>>> s.bar((int* p){ ++*p; });
>>>
>>> Huh? inout is for functions, which don't modify their arguments.
>>
>> With Jakob's code working, this would not be warranted.
>
> Huh? See rationale in https://issues.dlang.org/show_bug.cgi?id=1961

The function doesn't modify `p` - it's modified by a callback that was accepted because it's known at the call-site that `p` is modifiable.

This is necessary for `inout` to work with callback functions, such as with internal iteration (i.e. `opApply`). It can be worked around exactly the same way you would work around it with functions that return a value - by duplicating the function. It is essentially the same problem and thus `inout` could easily be used to fix it.
September 14, 2014
On Saturday, 13 September 2014 at 23:41:55 UTC, Timon Gehr wrote:
> All the examples there keep their non-modification guarantees.
> Modifications to inout parameters are visible at the call site.

Modifications are visible if you know the inout argument will be passed to the delegate, i.e. if you know the callee's implementation, and can't reason about behavior of inout argument just by seeing it being inout.

> E.g. the inout qualifier of the enclosing function should still be fully compatible with _itself_ even when data is accessed and modified from the nested function.

Yeah, I think, it's logical if the nested function is just a fragment of enclosing function; that way nested functions can be created without hindering access to variables of enclosing function.
September 14, 2014
On Sunday, 14 September 2014 at 01:38:33 UTC, Jakob Ovrum wrote:
> This is necessary for `inout` to work with callback functions, such as with internal iteration (i.e. `opApply`).

Can you write a pass and xfail test for it? This scenario looks non-trivial.

> It can be worked around exactly the same way you would work around it with functions that return a value - by duplicating the function. It is essentially the same problem and thus `inout` could easily be used to fix it.

Can you elaborate? I don't quite understand, what you mean.
September 14, 2014
On 09/14/2014 10:47 AM, Kagamin wrote:
> On Saturday, 13 September 2014 at 23:41:55 UTC, Timon Gehr wrote:
>> All the examples there keep their non-modification guarantees.
>> Modifications to inout parameters are visible at the call site.
>
> Modifications are visible if you know the inout argument will be passed
> to the delegate, i.e. if you know the callee's implementation,

The circumstances under which a callback will be invoked are hardly implementation details.

> and can't reason about behavior of inout argument just by seeing it being inout.
> ...

Most inout functions don't also take an inout callback.