Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
July 10, 2017 pure factory function vs immutable(Foo)** | ||||
---|---|---|---|---|
| ||||
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 |
July 10, 2017 Re: pure factory function vs immutable(Foo)** | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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`
|
July 10, 2017 Re: pure factory function vs immutable(Foo)** | ||||
---|---|---|---|---|
| ||||
Posted in reply to drug | 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; } ---- |
July 11, 2017 Re: pure factory function vs immutable(Foo)** | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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 |
July 11, 2017 Re: pure factory function vs immutable(Foo)** | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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
|
Copyright © 1999-2021 by the D Language Foundation