Why do "const inout" and "const inout shared" exist?

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Sat Jul 1 23:39:49 PDT 2017


On Sun, Jul 02, 2017 at 06:49:39AM +0200, Timon Gehr via Digitalmars-d 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.

Whoa, wait a second here.  Isn't this completely over-engineering
something that's actually quite simple?!

The idea of inout is that a function's parameter is essentially const,
and the function body treats it like const, and returns it as-is.
Therefore, it is it safe for the *caller* to assume that if the argument
is mutable, then the function's return value is also mutable.  This last
part is essentially the only reason inout exists; otherwise we would
just write it as const.

If the function may possibly return something other than the inout
argument, then it is actually wrong to annotate the parameter as inout
(e.g., pass in a mutable object, get an immutable back which the caller
thinks is mutable).  In such a case, the correct annotation is const,
not inout.

In your example, inout makes no sense at all. It should be written as:

	const(char)[] foo(bool condition, const(char)[] chars)

because if it returns the argument, then it's const(char)[], and if it
returns an immutable global, then immutable(char)[] implicitly converts
to const(char)[].  Using inout doesn't make sense here because you
cannot assume that the return value is mutable if the parameter is
mutable -- the function may return immutable instead.


T

-- 
"Holy war is an oxymoron." -- Lazarus Long


More information about the Digitalmars-d mailing list