"Steven Schveighoffer" , dans le message (digitalmars.D.learn:30255), a écrit : > On Fri, 21 Oct 2011 11:20:01 -0400, Christophe > <trav...@phare.normalesup.org> wrote: > >> "Daniel Murphy" , dans le message (digitalmars.D.learn:30139), a écrit : >>> "bearophile" <bearophileh...@lycos.com> wrote in message >>> news:j7jepi$prp$1...@digitalmars.com... >>>> Daniel Murphy: >>>> >>>>> 2) >>>>> immutable(int[]) fun() { return new int[]; } // conversion happens >>>>> here >>>>> immutable x = fun(); >>>>> >>>>> Bearophile's example is of the second, where it definately matters >>>>> what >>>>> the >>>>> purity of the function is. >>>> >>>> This is the enhancement request I have written days ago: >>>> http://d.puremagic.com/issues/show_bug.cgi?id=6783 >>>> >>>> Bye, >>>> bearophile >>> >>> Yes, and the problem in that report is that the function is const-pure, >>> not >>> strong-pure. >>> Without checking if the return type can contain a non-immutable >>> reference >>> from the arguments, it is not safe to implicitly convert the result to >>> immutable. >>> >>> eg. >>> immutable(int[]) foo(in int[] x) { return x; } >>> auto g = [1, 2, 3]; >>> auto a = foo(g.idup); //safe >>> auto b = foo(g); // unsafe >>> >>> Checking at the call site is possible, but not from inside the function. >>> >>> int[] foo(in int[] x) { return new int[](3); } >>> auto g = [1, 2, 3]; >>> immutable a = foo(g.idup); // safe >>> immutable b = foo(g); // unsafe, and easily rejected >>> >>> In your example, it is safe as the argument is not returned. Allowing >>> this >>> in the general case requires checking (recursively) that the return type >>> does not contain any types that any of the arguments can implicitly >>> convert >>> to that are non-immutable. >> >> What is the rule ? > > The theoretical rule should be, if it can be proven (except for the case > where a cast is used) the result is not a subset of the input, then the > result can be implicitly cast to immutable. > > The actual rule may be more conservative, since it may be difficult to > prove it.
OK, it must be proven from the signature of the function alone, and not from the function body. >> The result of >> pure int[] foo(in int[] x); >> is castable to immutable, since elements of x are not supposed to escape >> the function. >> >> The result of >> pure int[] foo(const int[] x); >> is not, because the value return by foo may be elements of x. > > Only via cast. How does foo legally change const int[] data to int[] data > without a cast? > > Note that the two functions you wrote are equivalent, since in translates > to "const scope" and scope does nothing to array parameters. > I meant: pure const(int)[] foo(const/in int[] x); But I thought scope was transitive like const, so it had effect on arrays. I find it pretty useless like that. A transitive scope could be very useful for purity checking and memory management optimisations. It would be useful for implicit casting to immutable too, even in no pure function. I may write about that later in another thread.