Jump to page: 1 2
Thread overview
[Issue 15651] filter: only parameters or stack based variables can be inout
Apr 18, 2018
Alex
Aug 14, 2019
Harry Vennik
Aug 16, 2019
Simen Kjaeraas
Aug 21, 2019
anonymous4
Aug 23, 2019
anonymous4
Aug 24, 2019
Harry Vennik
Aug 25, 2019
Harry Vennik
Aug 29, 2019
anonymous4
Mar 19, 2021
anonymous4
Dec 17, 2022
Iain Buclaw
April 18, 2018
https://issues.dlang.org/show_bug.cgi?id=15651

Alex <sascha.orlov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |sascha.orlov@gmail.com

--
August 14, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

Harry Vennik <htvennik@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |htvennik@gmail.com

--
August 16, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com
          Component|dmd                         |phobos

--- Comment #1 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
This issue is only partially fixable - filter() could use the solution
described in issue 13428 to turn inout(T) into const(T). This would lead to
fun() returning a const(D)[] result instead of inout(D)[], so it's not a
complete solution.

A complete solution, in fact, is not actually possible - consider the case of
returning SomeStruct!(inout(D)). inout(D) is only a valid type inside the inout
function - after returning, inout(D) should turn into D, const(D), or
immutable(D). That means SomeStruct!(inout(D)) should turn into
SomeStruct!(const(D)) or one of the other constancy variations, and this type
might be completely different from SomeStruct!(inout(D)), due to the way D's
templates work. Perhaps a solution could be found to this problem, but it would
very likely require a DIP.

--
August 21, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

anonymous4 <dfj1esp02@sneakemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=9983

--- Comment #2 from anonymous4 <dfj1esp02@sneakemail.com> ---
See also workaround in issue 9983

--
August 22, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

Steven Schveighoffer <schveiguy@yahoo.com> changed:

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

--- Comment #3 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Simen Kjaeraas from comment #1)
> This issue is only partially fixable - filter() could use the solution
> described in issue 13428 to turn inout(T) into const(T). This would lead to
> fun() returning a const(D)[] result instead of inout(D)[], so it's not a
> complete solution.

It's fully fixable -- if we can create an filter of inout elements. As I mentioned in issue 9983, this simply involves allowing structs to declare inout members. In fact, we should allow inout to be used ANYWHERE, except global variables (as putting inout variables in global space can change the meaning from call to call). They will just be another type of immutable in functions which don't have inout parameters, or when used in structs outside of inout functions.

(In reply to anonymous4 from comment #2)
> See also workaround in issue 9983

This is not a valid workaround, as an inout filter would not be iterable.

I actually thought that maybe with closures, we could make a "workaround" but it doesn't work because there's no way to return an inout from a function that has no inout parameters. Another stupid limitation that we should omit.

I'd try my hand at an inout improvement DIP, but I feel it would likely be rejected on principle, since inout is so disfavored by leadership.

--
August 23, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

--- Comment #4 from anonymous4 <dfj1esp02@sneakemail.com> ---
It will need separation between collections and iterators
---
struct A
{
        int[][] a;
        inout(int[])[] f() inout
        {
                return a.filter(x=>x!=null).array;
        }
}

inout(FilterCollection) filter(inout int[][] r, bool function(const int[])
pred)
{
        return inout FilterCollection(r,pred);
}

struct FilterCollection
{
        int[][] r;
        bool function(const int[]) pred;
        FilterRange range() const
        {
                auto r=FilterRange(&this);
                r.next();
                return r;
        }
}

struct FilterRange
{
        const(FilterCollection)* src;
        long index;
        inout(int[]) front(ref inout FilterCollection src2)
        {
                assert(src==&src2);
                return src2.r[index];
        }
        void popFront()
        {
                index++;
                next();
        }
        package void next()
        {
                foreach(i,a;src.r[index..$])
                {
                        if(src.pred(a)){ index+=i; return; }
                }
                index=src.r.length;
        }
        bool empty()
        {
                return index==src.r.length;
        }
}

inout(int[])[] array(inout FilterCollection src)
{
        inout FilterCollection c=src;
        inout(int[])[] a;
        auto r=c.range;
        while(!r.empty)
        {
                //a~=r.front(c);
                inout int[] b=r.front(c);
                a~=b;
                r.popFront();
        }
        return a;
}

int main()
{
        A a;
        int[][4] b;
        b[0]=[1];
        b[3]=[2];
        a.a=b;
        int[][] c=a.f;
        assert(c.length==2);
        assert(c[0][0]==1);
        assert(c[1][0]==2);
        return 0;
}
---

--
August 24, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

--- Comment #5 from Harry Vennik <htvennik@gmail.com> ---
(In reply to Steven Schveighoffer from comment #3)
> I'd try my hand at an inout improvement DIP, but I feel it would likely be rejected on principle, since inout is so disfavored by leadership.

I already have a partial draft. But as the discussion on various inout related issues evolved, I stopped writing for the moment, as there seem to be quite different opinions. My intent was to keep inout semantics the same as much as possible. The main proposal in my draft is to allow a function that somehow has acces to an inout variable from an enclosing scope to return inout.

This requires some additional scoping rules for delegates to prevent escaping references to inout variables. In theory DIP25 already gets close, though its implementation currently does not seem to detect return ref violations that involve delegates.

About inout fields in structs: I think those could be allowed inside inout functions, but such struct should not be allowed to escape from the scope of that function.

--
August 25, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

--- Comment #6 from Harry Vennik <htvennik@gmail.com> ---
(In reply to Steven Schveighoffer from comment #3)
> In fact, we should allow inout to be used ANYWHERE, except global variables (as putting inout variables in global space can change the meaning from call to call). They will just be another type of immutable in functions which don't have inout parameters, or when used in structs outside of inout functions.

There have to be more restrictions. The problem is that inout is not really a type modifier like const or immutable, rather it is a type modifier placeholder. Even when disallowing inout variables in global space, structs or class instances with inout members might still reference global data. Those may even have inout member functions, redefining the meaning of inout on every call. Inout would become the perfect way to modify immutable data with no way for the compiler to detect it:

----

class C
{
    private inout(int)[] _arr;

    this(inout int[] a)
    {
        _arr = a;
    }

    ref inout(int) getRef(size_t i) inout
    {
        return _arr[i];
    }
}

void main()
{
    immutable int[] iArr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

    /* inout resolves to immutable in constructor call */
    auto c = new C(iArr);

    /* inout resolves to mutable in call to getRef */
    c.getRef(5) = 8;  // Undefined behavior
}

----

--
August 28, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

--- Comment #7 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Harry Vennik from comment #6)
>     /* inout resolves to mutable in call to getRef */
>     c.getRef(5) = 8;  // Undefined behavior

That would fail because c.getRef(5) would return ref const(int). In order to allow inout modifiers on structs or classes, you need to consider the type modifier of those members in the inout placeholder calculation. In this case, you have mutable C and inout C._arr, which result in const.

In other words, the rules aren't written yet, but they can be constructed in a valid way. What we would be trying to accomplish is allowing encapsulation of functionality in a struct or class, even with inout data. Most likely you don't write getRef as an inout function.

--
August 29, 2019
https://issues.dlang.org/show_bug.cgi?id=15651

--- Comment #8 from anonymous4 <dfj1esp02@sneakemail.com> ---
If you want the mutable ranges to process inout data, they should be able to return inout data unless you want to do the front(inout collection) thing.

--
« First   ‹ Prev
1 2