Bug 12282 – Immutable result of std.array.array

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-03-01T08:47:19Z
Last change time
2017-10-30T15:15:32Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2014-03-01T08:47:19Z
I am not sure if this is an enhancement: void main() { import std.array: array; const a = [1]; immutable b = a.array; } DMD 2.066alpha gives: test.d(4,20): Error: cannot implicitly convert expression (array(a)) of type const(int)[] to immutable(int[]) Another example shows the same problem: void main() pure { import std.range: transversal; import std.array: array; const m = [[1.0, 2.0], [3.0, 4.0]]; immutable first = m.transversal(0).array; }
Comment #1 by monarchdodra — 2014-03-09T14:00:09Z
I don't think that can work, at least, not without massive help from the compiler, and the language itself. Let's forget `array` itself for a moment. Basically, you want the `const(int)[]` to cast to `immutable(int)[]`. Both you and I know that this conversion is not legal. You are probably thinking: Since `array` is pure, then the "uniqueness" of the result should make the cast possible? Yes and no... The problem is that `array` *also* takes an array as an argument, which may reference mutable data, making the function weakly pure. The language has no way to know if the return value isn't aliasing something in the input argument. Take this example ```D void main() { int a[]; immutable b = array(); //OK immutable c = array(null); //OK immutable d = array(a); //OK? } const(int[]) array( ) pure {return (int[]).init;} const(int[]) array(const(int[]) p) pure {return p;} ``` Currently, 1) and 2) pass, but 3) fails. For a good reason. So, unless the language gives us some sort of "noalias" for the return value, I don't see how your request could be implemented. The only way I see for it to work would be for `array` to *actually* return an immutable when possible. But: 1) The code would be difficult to write. 2) It would break auto-inference, since the expected return is "const", and not "immutable". I'm not closing, because it is a valid request, but I don't see any way of making it happen.
Comment #2 by bearophile_hugs — 2014-03-09T14:26:13Z
(In reply to comment #1) > I'm not closing, because it is a valid request, but I don't see any way of > making it happen. Thank you for your answers :-) In general if a request is impossible there's not much sense in keeping it open. But let's keep this open for some more time. > const(int[]) array( ) pure {return (int[]).init;} > const(int[]) array(const(int[]) p) pure {return p;} > ``` > > Currently, 1) and 2) pass, but 3) fails. For a good reason. > > So, unless the language gives us some sort of "noalias" for the return value, If you have a function like this: int[] array(scope const int[] a) pure {} Or even like this: int[] array(scope int[] a) pure {} The input is const, so it can't be mutated, ints don't have indirections, and "scope" once implemented means the input data can't escape the array function. Is this enough to be able to cast the result to immutable?
Comment #3 by monarchdodra — 2014-03-09T14:37:18Z
(In reply to comment #2) > If you have a function like this: > > int[] array(scope const int[] a) pure {} > > Or even like this: > > int[] array(scope int[] a) pure {} > > The input is const, so it can't be mutated, Isn't it only const with "in" ? Not that it makes an actual difference here. > Is this enough to be able to cast the result to immutable? Actually, maybe. It's the "help from the compiler, and the language itself" I was talking about, and the "noalias" type qualifier. > ints don't have indirections, and > "scope" once implemented means the input data can't escape the array function. I'm not fluent with how `scope` would work, but I fear it would not work for generic types, which may themselves have indirections. Would this be legal? Or would it violate the "scope" constraint? int*[] array(scope int*[] a) pure {}
Comment #4 by bearophile_hugs — 2014-03-09T15:11:59Z
(In reply to comment #3) > Isn't it only const with "in" ? Not that it makes an actual difference here. "in" means "scope const". Currently scope is not implemented, there is no DIP and no one knows if and when it is coming. > but I fear it would not work for > generic types, which may themselves have indirections. I think it can't work for generic types, unless D adds a region typing as Rust. > Would this be legal? Or would it violate the "scope" constraint? > > int*[] array(scope int*[] a) pure {} Kenji, Walter, Timon and Andrei are the few persons able to think about all the cases that can happen :)
Comment #5 by andrei — 2017-10-30T15:15:32Z