Bug 5081 – Pure functions as initializers for immutable structures

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2010-10-19T11:49:00Z
Last change time
2011-08-24T20:51:28Z
Keywords
patch
Assigned to
nobody
Creator
tomeksowi

Comments

Comment #0 by tomeksowi — 2010-10-19T11:49:42Z
From my post on D newsgroup: Initializing immutable structures is a source of constant grief. Anything non-trivial requires instancing a mutable structure, initializing it, and then either casting to immutable (it's up to you to ensure no alias leaked) or, not to violate the type system, duplicate the whole. Yet, if there was a situation where the alias leaking is under control, casting would be safe. Perhaps pure* functions are such a place. They can only touch the immutable world, whether through globals or through their parameters. So if one initializes the returned structure with a reference to the outside world, it will be immutable. And if you stuff the structure with anything mutable, it must have been created within the function's body, so no alias leaks. I think it is safe to implicitly convert a pure function's return value to immutable. * here by pure I mean either the old pure** when it still had immutable arguments, or Don's "immutably pure". Pure functions could be used as follows: pure T make(Args args) { ... } unittest { T t = make(...); // good immutable T t = make(...); // also good } Michel Fortin also noticed a nice-to-have: if at the call site you know that all the arguments you're feeding the function with are immutable, then you can automatically cast the result to immutable, even if the function can also accept const arguments.
Comment #1 by bearophile_hugs — 2010-10-31T16:31:54Z
See also bug 5147 for a different solution
Comment #2 by schveiguy — 2011-02-24T12:47:49Z
(In reply to comment #0) > Michel Fortin also noticed a nice-to-have: if at the call site you know that > all the arguments you're feeding the function with are immutable, then you can > automatically cast the result to immutable, even if the function can also > accept const arguments. Note actually that as long as you can verify the return value did not come directly from the parameters, it's also possible to implicitly cast to immutable. For example: pure T[] mydup(T)(const(T)[] param) {...} It's provable that the return value did not come from param (without a cast), because you can't implicitly cast param to T[]. So you can cast the result to immutable, even if param began as mutable. This might be really tricky to implement though, there can be all sorts of weird cases. But if this could be accomplished, it would completely negate the need for idup.
Comment #3 by yebblies — 2011-07-08T20:11:16Z
Comment #4 by bugzilla — 2011-08-24T19:48:32Z
Comment #5 by bearophile_hugs — 2011-08-24T20:31:58Z
This is a new part of the design of D purity, and a significant improvement for D usability. I think the behaviours shown by this little program are correct, but I think that error message needs to be improved (completed with more details), because in some cases (like foo1) that's an acceptable operation: string foo1() pure { const(char[]) s2 = ['a']; return s2; } string foo2() pure { return ['a']; } string foo3(immutable char[] s) pure { return s; } string foo4(in char[] s1, immutable char[] s2) pure { return s2; } string foo5(in char[] s) pure { return s; // Error: cannot implicitly convert expression (s) of type const(char[]) to string } void main() { immutable r1 = foo1(); // OK immutable r2 = foo2(); // OK immutable r3 = foo3(['a']); // OK immutable r4 = foo4(['a'], ['b']); // OK immutable r5 = foo5(['a']); // Error } Good and complete error messages are needed to help the programmer understand her mistake and build a correct model of D semantics in her head.
Comment #6 by bearophile_hugs — 2011-08-24T20:51:28Z
(In reply to comment #5) > I think the behaviours shown... Sorry, that was out of place in this enhancement request. I have opened bug 6553 for it.