Re: pure factory function vs immutable(Foo)**

2017-07-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/11/17 2:12 PM, ag0aep6g wrote:

On 07/10/2017 04:57 PM, ag0aep6g wrote:


alias T = int;

T** f(const T** input) pure
{
 T** output;
 return output;
}

void main()
{
 T i;
 T* p = &i;
 immutable T** r = f(&p);
}


[...]
Now change `T` to `alias T = immutable int;`. The program gets 
rejected. The error message is: "cannot implicitly convert expression 
(f(& p)) of type immutable(int)** to immutable(int**)".


Filed an issue:
https://issues.dlang.org/show_bug.cgi?id=17635


I think this is a legitimate bug.

to make sure this is correct, I added:

pragma(msg, typeof(input).stringof);

And it prints const(immutable(int)**) (as I would have expected, but 
wasn't 100% sure).


So there is no way the input can be returned, as immutable(int)** cannot 
be implicitly converted from const(immutable(int)**).


I think this is just a missed case in the compiler.

-Steve


Re: pure factory function vs immutable(Foo)**

2017-07-11 Thread ag0aep6g via Digitalmars-d-learn

On 07/10/2017 04:57 PM, ag0aep6g wrote:


alias T = int;

T** f(const T** input) pure
{
 T** output;
 return output;
}

void main()
{
 T i;
 T* p = &i;
 immutable T** r = f(&p);
}


[...]
Now change `T` to `alias T = immutable int;`. The program gets rejected. 
The error message is: "cannot implicitly convert expression (f(& p)) of 
type immutable(int)** to immutable(int**)".


Filed an issue:
https://issues.dlang.org/show_bug.cgi?id=17635


Re: pure factory function vs immutable(Foo)**

2017-07-10 Thread ag0aep6g via Digitalmars-d-learn

On 07/10/2017 05:42 PM, drug wrote:

10.07.2017 17:57, ag0aep6g пишет:

[...]

The error message is: "cannot implicitly convert expression (f(& p)) of
type immutable(int)** to immutable(int**)".

[...]

I'm not sure I understand, but
```
immutable (T)** r = f(&p);
```
compiles. So compiler complains that indirections are mutable, but 
immutable ones are expected according to type of `r`


In itself, the error message makes sense. We can't usually convert from 
`immutable(int)**` to `immutable(int**)`.


We also can't usually convert from `int**` to `immutable(int**)`. But we 
can when the `int**` comes from a "pure factory function". And as far as 
I can see, it could/should also work when the pure factory function 
returns `immutable(int)**`.


For some context, I originally tried something like this:


struct S
{
string str;
int other_stuff;
}

void main()
{
import std.algorithm: map;
import std.array: array;
S[] structs;
immutable strs = structs.map!(s => s.str).array;
}



Re: pure factory function vs immutable(Foo)**

2017-07-10 Thread drug via Digitalmars-d-learn

10.07.2017 17:57, ag0aep6g пишет:

I feel like I must be missing something here.

This works:


alias T = int;

T** f(const T** input) pure
{
T** output;
return output;
}

void main()
{
T i;
T* p = &i;
immutable T** r = f(&p);
}


`f` is `pure`, its parameter is const, and its return type has mutable
indirections. That makes it a "pure factory function" [1].

Since `f` is a pure factory function, the compiler can assume that the
result is not referenced from anywhere else. So I can declare it
`immutable`.

So far, so good.

Now change `T` to `alias T = immutable int;`. The program gets rejected.
The error message is: "cannot implicitly convert expression (f(& p)) of
type immutable(int)** to immutable(int**)".

What changed? `f` can now return a reference to `i`. But that's not a
problem, because that part of the return type is already `immutable`.
What would be a problem is if `f` could return a reference to `p`. But
it can't, as far as I can tell.

Am I missing something or could/should the program be accepted with `T =
immutable int`? What could `f` do that would break `r`'s immutability?


[1] https://dlang.org/spec/function.html#pure-functions

I'm not sure I understand, but
```
immutable (T)** r = f(&p);
```
compiles. So compiler complains that indirections are mutable, but 
immutable ones are expected according to type of `r`




pure factory function vs immutable(Foo)**

2017-07-10 Thread ag0aep6g via Digitalmars-d-learn

I feel like I must be missing something here.

This works:


alias T = int;

T** f(const T** input) pure
{
T** output;
return output;
}

void main()
{
T i;
T* p = &i;
immutable T** r = f(&p);
}


`f` is `pure`, its parameter is const, and its return type has mutable 
indirections. That makes it a "pure factory function" [1].


Since `f` is a pure factory function, the compiler can assume that the 
result is not referenced from anywhere else. So I can declare it 
`immutable`.


So far, so good.

Now change `T` to `alias T = immutable int;`. The program gets rejected. 
The error message is: "cannot implicitly convert expression (f(& p)) of 
type immutable(int)** to immutable(int**)".


What changed? `f` can now return a reference to `i`. But that's not a 
problem, because that part of the return type is already `immutable`. 
What would be a problem is if `f` could return a reference to `p`. But 
it can't, as far as I can tell.


Am I missing something or could/should the program be accepted with `T = 
immutable int`? What could `f` do that would break `r`'s immutability?



[1] https://dlang.org/spec/function.html#pure-functions