[Issue 19125] IFTI and inout removes head mutability qualifier on by-val parameters

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Jul 30 13:16:55 UTC 2018


https://issues.dlang.org/show_bug.cgi?id=19125

Steven Schveighoffer <schveiguy at yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy at yahoo.com

--- Comment #1 from Steven Schveighoffer <schveiguy at yahoo.com> ---
The issue here is that IFTI applies inout to the head when it shouldn't

If you have a function like this:

struct S(T)
{
   T t;
}

inout(S!T) makeS(T)(inout(T) t)
{
   return inout S!T(t);
}

One expects the type parameter of S to match the type parameter passed in.
inout is just saying "I'm not going to change anything"

However, in the case of types that have tail-mutability modifier capability
(pointers, arrays), IFTI is pulling the mutability OUT from the tail and
applying it to the entire parameter:

auto s1 = makeS("hello");
assert(is(typeof(s1) == immutable(S!(char[])));
auto s2 = makeS("hello".ptr);
assert(is(typeof(s2) == immutable(S!(char *));

But tail-modified values are distinctly more capable in terms of mutability
than fully modified values. So IFTI I believe should NOT perform this
adjustment, and just match T as string (and therefore the type of t should be
inout(string)).

If one wishes to actually match inout to the modifier of the tail, one can do
so with a specialization:

auto makeS(T)(inout(T)[] t)
{
   return inout S!(T[])(t);
}

Note that the use of auto ref in the original code is affecting what is
inferred, because of the double-indirection rule. This makes it doubly
confusing (see the cases for wrap0("foo") and wrap0(s0), which one might expect
to be identical ).

--


More information about the Digitalmars-d-bugs mailing list