July 02, 2017
On Saturday, 1 July 2017 at 23:08:40 UTC, Andrei Alexandrescu wrote:
> On 07/01/2017 06:12 PM, Timon Gehr wrote:
>> On 01.07.2017 23:47, Andrei Alexandrescu wrote:
>>> Walter looked at http://erdani.com/conversions.svg and said actually "const inout" and "const inout shared" should not exist as distinct qualifier groups, leading to the simplified qualifier hierarcy in http://erdani.com/conversions-simplified.svg.
>>>
>>> Are we missing something?
>> 
>> I don't think so.
>> 
>>> Is there a need for combining const and inout?
>>> ...
>> 
>> In DMD's implementation, yes. (Combinations of qualifiers are represented as integers instead of nested AST nodes.)
>> 
>> const(const(T))     = const(T)
>> const(immutable(T)) = immutable(T)
>> const(inout(T))     = ?
>> 
>> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.
>> 
>> The simplified hierarchy is enough though. The more complex one can be derived from it. Since S -> const(S) for all S, it directly follows that inout(T) -> const(inout(T)) for all T (we can choose S=inout(T)).
>
> Thanks! Well I do want to have a hierarchy with all possible qualifier combinations for utmost clarity. Only the combinations listed are valid, e.g. there's no "immutable inout" or whatever.
>
> Vaguely related question: should "const" convert implicitly to "const shared"? The intuition is that the latter offers even less guarantees than the former so it's the more general type. See http://erdani.com/conversions3.svg.
>
> That would be nice because we have "const shared" as the unique root of the qualifier hierarchy.
>
>
> Andrei

I cannot think so a single time I ever used const inout.
July 02, 2017
On 02.07.2017 03:22, Stefan Koch wrote:
> ...
> 
> I cannot think so a single time I ever used const inout.

I'll boldly claim that this is true mostly because you have never used 'inout'. ;)
July 01, 2017
On 7/1/2017 3:12 PM, Timon Gehr wrote:
> const(const(T))     = const(T)
> const(immutable(T)) = immutable(T)
> const(inout(T))     = ?
> 
> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.

If const(inout(T)) is reduced to inout(T), it works.
July 02, 2017
On Sunday, 2 July 2017 at 01:51:05 UTC, Timon Gehr wrote:
> On 02.07.2017 03:22, Stefan Koch wrote:
>> ...
>> 
>> I cannot think so a single time I ever used const inout.
>
> I'll boldly claim that this is true mostly because you have never used 'inout'. ;)

affirmative
July 01, 2017
On 7/1/2017 6:22 PM, Stefan Koch wrote:
> I cannot think so a single time I ever used const inout.

The math needs to work whether it is ever used or not, otherwise we wind up with bizarre, intractable absurdities.
July 02, 2017
On 02.07.2017 05:13, Walter Bright wrote:
> On 7/1/2017 3:12 PM, Timon Gehr wrote:
>> const(const(T))     = const(T)
>> const(immutable(T)) = immutable(T)
>> const(inout(T))     = ?
>>
>> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.
> 
> If const(inout(T)) is reduced to inout(T), it works.

Counterexample:

const(inout(char))[] foo(bool condition, inout(char)[] chars){
    if(!condition) return "condition failed!";
    return chars;
}

Turn const(inout(char)) into inout(char) and the example no longer compiles. (Nor should it.)
July 02, 2017
On Sunday, 2 July 2017 at 03:55:37 UTC, Walter Bright wrote:
> On 7/1/2017 6:22 PM, Stefan Koch wrote:
>> I cannot think so a single time I ever used const inout.
>
> The math needs to work whether it is ever used or not, otherwise we wind up with bizarre, intractable absurdities.

I agree.

I may add though that we already have a few absurdities ...

inout itself for example :)
July 01, 2017
On 7/1/2017 9:12 PM, Timon Gehr wrote:
> On 02.07.2017 05:13, Walter Bright wrote:
>> On 7/1/2017 3:12 PM, Timon Gehr wrote:
>>> const(const(T))     = const(T)
>>> const(immutable(T)) = immutable(T)
>>> const(inout(T))     = ?
>>>
>>> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.
>>
>> If const(inout(T)) is reduced to inout(T), it works.
> 
> Counterexample:
> 
> const(inout(char))[] foo(bool condition, inout(char)[] chars){
>      if(!condition) return "condition failed!";
>      return chars;
> }
> 
> Turn const(inout(char)) into inout(char) and the example no longer compiles. (Nor should it.)

I don't think that matters. There's no reason to write const(inout) for a return value.
July 02, 2017
On 02.07.2017 06:45, Walter Bright wrote:
> On 7/1/2017 9:12 PM, Timon Gehr wrote:
>> On 02.07.2017 05:13, Walter Bright wrote:
>>> On 7/1/2017 3:12 PM, Timon Gehr wrote:
>>>> const(const(T))     = const(T)
>>>> const(immutable(T)) = immutable(T)
>>>> const(inout(T))     = ?
>>>>
>>>> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.
>>>
>>> If const(inout(T)) is reduced to inout(T), it works.
>>
>> Counterexample:
>>
>> const(inout(char))[] foo(bool condition, inout(char)[] chars){
>>      if(!condition) return "condition failed!";
>>      return chars;
>> }
>>
>> Turn const(inout(char)) into inout(char) and the example no longer compiles. (Nor should it.)
> 
> I don't think that matters. There's no reason to write const(inout) for a return value.


I think the example demonstrate the reason. It either returns the argument or an immutable global. If the argument is immutable, so is the return value, otherwise the return value is const.
July 01, 2017
On 7/1/2017 9:49 PM, Timon Gehr wrote:
> On 02.07.2017 06:45, Walter Bright wrote:
>> On 7/1/2017 9:12 PM, Timon Gehr wrote:
>>> On 02.07.2017 05:13, Walter Bright wrote:
>>>> On 7/1/2017 3:12 PM, Timon Gehr wrote:
>>>>> const(const(T))     = const(T)
>>>>> const(immutable(T)) = immutable(T)
>>>>> const(inout(T))     = ?
>>>>>
>>>>> It used to be the case that const(inout(T)) = const(T), but this is wrong, because if we replace 'inout' by 'immutable', the result should be immutable(T), not const(T). Hence const(inout(T)) cannot be reduced further.
>>>>
>>>> If const(inout(T)) is reduced to inout(T), it works.
>>>
>>> Counterexample:
>>>
>>> const(inout(char))[] foo(bool condition, inout(char)[] chars){
>>>      if(!condition) return "condition failed!";
>>>      return chars;
>>> }
>>>
>>> Turn const(inout(char)) into inout(char) and the example no longer compiles. (Nor should it.)
>>
>> I don't think that matters. There's no reason to write const(inout) for a return value.
> 
> 
> I think the example demonstrate the reason. It either returns the argument or an immutable global. If the argument is immutable, so is the return value, otherwise the return value is const.

The purpose of inout is to transmit the mutable/const/immutable attribute of the argument to the return type. If you want the return type to be const, mark it const, not const inout.

I can't think of any useful purpose to const inout.

The foo() example is bogus anyway. The return type inout calculus has nothing to  do with the return expressions. It's not going to be immutable if the `return "condition failed";` is executed. It only depends on the attribute of the argument to the `chars` parameter.