relax inout rules?

kenji hara k.hara.pg at gmail.com
Tue Dec 13 00:41:50 PST 2011


2011/12/13 Steven Schveighoffer <schveiguy at yahoo.com>:
> Currently, the rules of inout say you cannot put inout on a parameter
> without putting it on the return type as well.  This makes sense, it gives
> the compiler one place to worry about whether implicit casting rules will
> properly work.
>
> But Timon Gehr brought up in another thread (started by Merdhad) that we can
> separate the resolution of inout from the applicability of the parameters.
>  Essentially, calling an inout function goes through two phases:
>
> 1. determine what inout resolves to
> 2. try and call the function.
>
> inout rules don't have to change regarding resolving inout's actual value.
>  In other words, if all inout places are matched as int, immutable, or
> inout, then inout resolves to that value.  Otherwise inout resolves to
> const.
>
> But what's different is (at least in my mind) the function call might not
> necessarily succeed even when the resolution is completed.
>
> Take for example:
>
> inout(int)* foo(inout(int)** a, inout(int)* b);
>
> Now, if we call foo like this:
>
> int a;
> int b;
> int* pa = &a;
>
> foo(&pa, &b);
>
> This means foo is called with (int **, int *).  This means inout resolves to
> mutable (no qualifier).  *NOW* we try calling foo as if it were written:
>
> int *foo(int **a, int *b)
>
> And it can be done.  Not only that, but there is nothing bad that could be
> happening in foo that should be disallowed by the compiler.
>
> Now let's see what happens were we *could* do something bad:
>
> immutable(int) c;
> auto pc = &c;
>
> foo(&pc, &b);
>
> Now, foo is being called with (immutable(int)**, int *).  Inout resolves to
> const (due to the mix of mutable and immutable).  *NOW* we try calling foo
> as if it were written:
>
> const(int)* foo(const(int)** a, const(int)* b);
>
> And it *FAILS*.  This is because you cannot implicitly convert
> immutable(int)** to const(int)** (well, at least it *shouldn't* compile, I'm
> not sure if it does currently).

Separating phases is good.
Current implementation does not separate the two phases, and I agree
that has a bug you appears.

And, we need fixing issue 4251 and 5493 to fill the hole of const system.
Today, I've posted a pull for it.
https://github.com/D-Programming-Language/dmd/pull/558

> What this does is allow more possibilities for inout than we currently do.
>  Because inout is not now tied to returning something, we can create
> functions that have inout parameters but no inout return value.
>
> The example we were discussing on the other thread was this:
>
> void foo(ref inout(int)* a, inout(int)* b) { a = b;}
>
> This would compile as long as you call with const(int)* as the first
> parameter, or if both parameters matched in constancy (i.e. both were
> immutable, both were mutable, or both were inout).
>
> This gives us more cases where you don't have to repeat functions for the
> sake of handling different types of constancy, particularly when we have
> mutable references 2 levels deep.  I can't see anything technically wrong
> with this, can anyone else?
>
> The one thing that I think still should be required is if you have inout on
> the return value, there *must* be an inout on a parameter.  Otherwise, the
> compiler has no idea what it should be (since we don't overload on return
> type in D).
>
> If this ends up being viable, this is actually easier to explain than the
> current rules for inout.  We just have to make sure the rules are sound
> before doing something like this.
>
> -Steve

Against an inout function that does not return inout type:
- the number of inout parameters should be 2 more?
- at least one parameter should have 'out' or 'ref' storage class as a
*return parameter*?

But I'm not sure these restrictions are necessarily required.

Kenji Hara


More information about the Digitalmars-d mailing list