D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 7310 - pure function results should implicitly cast to mutable, shared, and inout
Summary: pure function results should implicitly cast to mutable, shared, and inout
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-18 10:51 UTC by timon.gehr
Modified: 2012-01-18 17:09 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description timon.gehr 2012-01-18 10:51:02 UTC
The following code should compile
immutable(int)[] foo()pure{return new int[1];}
void main(){int[] x = foo();}

as should this (alternatively it should error out on the first line, not on the second):
const(int)[] foo()pure{return new int[1];}
void main(){int[] x = foo();}
Comment 1 timon.gehr 2012-01-18 11:55:27 UTC
On second thought, this should be the case for all type qualifiers.
The following code should compile too:

inout(int)[] foo(inout int)pure{return new int[1];}
shared(int)[] foo()pure{return new int[1];}
int[] bar()pure{return new int[1];}
inout(int)[] bar(inout int){inout r = bar(); return r;}
void main(){shared(int)[] a = bar();}
Comment 2 timon.gehr 2012-01-18 12:01:45 UTC
Of course, there have to be some additional constraints: Namely, if the return value should implicitly convert to <qualifier>, the function parameters all have to implicitly convert to <qualifier>. This could even be checked at call site:

const(int)[] foo(const(int)[] x)pure{return x;}
void main(){
    int[] x = new int[1];
    int[] y = foo(x); // perfectly fine
}
Comment 3 Stewart Gordon 2012-01-18 15:32:54 UTC
I'm not sure about this.  If a function is pure, then multiple calls with the same arguments (or even that return the same value) can potentially be optimised to all use the same copy of the data.  Implicit cast to mutable would mess this up, unless we define the implicit conversion to .dup the result.
Comment 4 timon.gehr 2012-01-18 15:40:51 UTC
The analysis would just have to detect whether or not such an implicit conversion has happened. The compiler has all the information, I don't think it is an issue.
Comment 5 timon.gehr 2012-01-18 15:42:35 UTC
Furthermore, the optimization also applies when it is the other way round (mutable return value implicitly converted to immutable), so the analysis would consider implicit conversions of the return value anyway.
Comment 6 Don 2012-01-18 16:57:39 UTC
(In reply to comment #5)
> Furthermore, the optimization also applies when it is the other way round
> (mutable return value implicitly converted to immutable), so the analysis would
> consider implicit conversions of the return value anyway.

No. The only way an immutably pure function can return a mutable value, is if it created it itself -- so we know it's unique. No analysis of the body of the function is required.

But, if an immutable pure function returns an immutable value, we know nothing. It could be a parameter, or an immutable global variable, or a variable created inside the function.
Comment 7 timon.gehr 2012-01-18 17:09:48 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > Furthermore, the optimization also applies when it is the other way round
> > (mutable return value implicitly converted to immutable), so the analysis would
> > consider implicit conversions of the return value anyway.
> 
> No. The only way an immutably pure function can return a mutable value, is if
> it created it itself -- so we know it's unique. No analysis of the body of the
> function is required.

This is not what I was suggesting. I am only reasoning about the call-site here.

> 
> But, if an immutable pure function returns an immutable value, we know nothing.
> It could be a parameter, or an immutable global variable, or a variable created
> inside the function.

For parameter, see comment #2. immutable global variables are a deal-breaker. Implicitly casting between shared and unshared should still be possible at strongly pure function border. I am opening a separate issue for it.